views:

938

answers:

3

I am starting to move more of my view hierarchy construction to IB.

I have a nib file called "AlignmentViewController.xib" in which I set up my view hierarchy with AlignmentViewController as the files owner. This works fine.

One of the methods I remain fuzzy on is awakeFromNib. In the follow code snippet of AlignmentViewController I add the single additional method awakeFromNib. However, it does NOT get called:

- (void)awakeFromNib {

   NSLog(@"AlignmentViewController - awakeFromNib");
   [super awakeFromNib];

}

- (id)initWithChromosomeName:(NSString *)chromosomeName 
               basepairStart:(NSUInteger)basepairStart 
                 basepairEnd:(NSUInteger)basepairEnd {

    self = [self initWithNibName:@"AlignmentViewController" bundle:nil];

    if (nil != self) {


     self.title         = @"Alignment";

     self.chromosomeName = chromosomeName;
     self.basepairStart = basepairStart;
     self.basepairEnd = basepairEnd;

     self.wantsFullScreenLayout = YES;

    }

    return self;
}

Can someone clarify for me what I have missed here?

Cheers, Doug

UPDATE: After reading some the the answers I realize I need to get to the bottom of something that is pretty fundamental.

Looking at the initialization:

- (id)initWithChromosomeName:(NSString *)chromosomeName 
               basepairStart:(NSUInteger)basepairStart 
                 basepairEnd:(NSUInteger)basepairEnd {

    self = [self initWithNibName:@"AlignmentViewController" bundle:nil];

I notice I am calling initWithNibName:bundle: indirectly. Is this bad practice? The AlignmentViewController.xib file defines my view hierarchy. But I'm not really using initWithNibName:bundle: in the typical way? Is there a better way to do this?

+6  A: 

-awakeFromNib is sent to all object that are instantiated from the nib after all nib objects have instantiated. The owner is not one of those objects. It exists prior to deserializing the nib and is wired to the nib after loading, so it is not sent -awakeFromNib (unless of course it is instantiated by some other nib itself).

One clue here is that there's no way both -initFromChromosomePair:basepairStart:basepairEnd: and -awakeFromNib could both be called. The nib loader always calls -initWithCoder:, -initWithFrame: or -init (the rules for which is sent are in The Nib Object Life Cycle). The fact that you have some other designated initializer strongly suggests that you're manually creating this object somewhere in the code, which means this object is not "awaken from nib."

Rob Napier
Thanks Rob, I guess I'm unclear on the semantics of initWithNibName:bundle:. Elsewhere in my code I do indeed call initWithChromosomeName:basepairStart:basepairEnd: which in turn calls initWithNibName:bundle: as shown above. Do no nib related methods fire as a result of using initWithNibName:bundle:?
dugla
Many fire; they just target the objects instantiated by the nib loader. The owner of the nib is not *in* the nib, and so does not get -awakeFromNib. -viewDidLoad gets sent to the view controller, which is where you would do things that need to be done after the nib finishes loading. Note that a view controller can be in a nib, so can receive both -awakeFromNib (when it is loaded from the parent nib) and then later -viewDidLoad (for when its own nib finishes loading). -awakeFromNib is sent to all objects in a nib after all objects in the nib have been instantiated and IBOutlet wired.
Rob Napier
Now I get it. Thanks Rob, that really clears things up. I was overlooking the fact that filesOwner is just a proxy, not a member of the nib. Coolness. Thanks a million Rob.
dugla
+1  A: 

Based on what you've told us, I believe I know what your problem is. awakeFromNib is called when an object is deserialized from a nib file. Here you have an object, which is the owner, that exists before the nib is loaded. Thus awakeFromNib would never be sent to your AlignmentViewController.h.

If you need to do something here, try using loadView instead. Or just do it after loading the nib. What is it that you're tying to do that you wanted to do it in awakeFromNib?

Gordon Worley
Thanks Gordon. Just trying to get better inution around the semantics and timing of nib related code. I'm in the process of relying more and more on IB for UI construction and I still unsure of how the IB world and the XCode worlds sync up. So, do no nib related methods fire do to my use of initWithNibName:bundle:?
dugla
No, it's that `awakeFromNib` isn't called on your controller, because your controller isn't in the nib. It will be called on all of the views and such that are in the nib.
Sixten Otto
Note that above where Gordon says "loadView," I believe he means "viewDidLoad." You generally should not mess with -loadView when dealing with nib-based view controllers.
Rob Napier
Sixten and Rob, very helpful. The fog is lifting. Enlightenment is imminent. Cheers.
dugla
+1  A: 

Just adding a clarification: -awakeFromNib is sent to File's Owner in Cocoa, but not Cocoa Touch.

From Apple's Docs:

...

  • It sends an awakeFromNib message to the appropriate objects in the nib file that define the matching selector:
    • In Mac OS X, this message is sent to any interface objects that define the method. It is also sent to the File’s Owner and any proxy objects that define it as well.
    • In iPhone OS, this message is sent only to the interface objects that were instantiated by the nib-loading code. It is not sent to File’s Owner, First Responder, or any other proxy objects.
dodgio