16

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?

gerry3
  • 21,420
  • 9
  • 66
  • 74
dugla
  • 12,774
  • 26
  • 88
  • 136
  • 2
    FWIW, UIViewController also provides `viewDidLoad` specifically for any processing you need to do in your controller, after the view has been loaded (whether manually or from a nib). – Sixten Otto Oct 19 '09 at 14:14
  • Yes. I make extensive use of viewDidLoad. I'm just trying to move more UI construction to IB and I need to deal with awakeFromNib at some point. – dugla Oct 19 '09 at 15:31
  • 3
    Use of IB does not mandate use of `awakeFromNib`, nor does it contradict use of `viewDidLoad`. – Sixten Otto Oct 19 '09 at 16:15

4 Answers4

40

-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
  • 286,113
  • 34
  • 456
  • 610
  • 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 Oct 19 '09 at 15:26
  • 4
    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 Oct 19 '09 at 17:01
  • 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 Oct 19 '09 at 18:38
  • Nice, I didn't realize that FileOwner doesn't gets this call as when the Nib's views are of a custom class. – htafoya Dec 13 '12 at 22:13
35

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
  • 2,169
  • 21
  • 19
2

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 Seidoh Worley
  • 7,839
  • 6
  • 45
  • 82
  • 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 Oct 19 '09 at 15:30
  • 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 Oct 19 '09 at 16:14
  • 1
    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 Oct 19 '09 at 17:02
  • Sixten and Rob, very helpful. The fog is lifting. Enlightenment is imminent. Cheers. – dugla Oct 19 '09 at 18:41
-2

You should override func awakeFromNib(). Not override class func awakeFromNib()

override func awakeFromNib() {
    super.awakeFromNib()
    setupContent()
}
Vitaliy
  • 25
  • 3