[super awakeFromNib]

Being my first blog post, it seems appropriate that I deal with awakeFromNib. I work for a software company developing websites on a Microsoft stack, but I've been playing around with Cocoa for almost a year now and it has been a lot of fun to work with. It is always challenging to work with a new technology and who doesn't like to work on a mac?

My hope is to share some things I've learned along the way as a software developer and help other people avoid the mistakes I've made. I got the idea of Coding Scars from my friend Ken, who mentored me as a programer. Just about every time I am pulling my hair out over some nasty bug and I call Ken over, he usually knows the answer in a few minutes. I tell him how incredible he is and he always says, "Scars, I just have more scars." So, hopefully those days when you trace down through the debugger or spend a week parsing web service xml, you are developing some coding scars that will serve you well later.

With that out of the way, I spent the last week trying to debug a nasty issue, that ended up being a dumb mistake. I had a subclassed NSWindowController that I was using to load a window from a nib and show it on the screen. My code to load the nib and show the window was as follows:

-(IBAction)showCustomWindow:(id)sender 
{
    if(!windowController){
        windowController = [[MyWindowController alloc] initWithWindowNibName:@"MyWindow"];
    }

    [windowController showWindow:self];
}

On a machine running 10.6 when showCustomWindow was called, the window would show as normal; however, on 10.5 the method would have to be called twice before the window would appear. I was using functions that were available on both 10.5 and 10.6 (10.0 for that matter), so I couldn't figure it out.

Finally, I bit the bullet and pulled down my project in XCode onto a machine running 10.5 and ran it through the debugger. I finally realized that my app was failing when the nib was loaded and a subclass of NSView in my nib called it's awakeFromNib function. My awakeFromNib looked like:

- (void)awakeFromNib
{
    [super awakeFromNib];

    .... bind to objects ....
}

Seemed perfectly normal to me! But, as I came to find out, not every super class implements awakeFromNib! So, when I called [super awakeFromNib] it failed with a "does not respond to selector". The simple solution is to take out the [super awakeFromNib], but a little more elegant solution is to check to see if the superclass responds to awakeFromNib, like so:

if([NSView instancesRespondToSelector:@selector(awakeFromNib)]) {
    [super awakeFromNib];
}

With that change, it worked like a dream. Note: I initially thought i could do:

if([super respondsToSelector:@selector(awakeFromNib)]) {
    [super awakeFromNib];
}

but, you can't call respondsToSelector on super in awakeFromNib, it seems to always return true. So, hopefully this has been helpful or informative and will save someone else some pain.

0 comments:

Post a Comment