Welcome to the MacNN Forums.

If this is your first visit, be sure to check out the FAQ by clicking the link above. You may have to register before you can post: click the register link above to proceed. To start viewing messages, select the forum that you want to visit from the selection below.

You are here: MacNN Forums > Software - Troubleshooting and Discussion > Developer Center > When to "init" and when to "awakeFromNib"

When to "init" and when to "awakeFromNib"
Thread Tools
Senior User
Join Date: Oct 2000
Location: Lawrence, KS
Status: Offline
Reply With Quote
Jun 9, 2001, 09:37 AM
 
In chapter 8, of Learning Cocoa we find a method as described below:

<BLOCKQUOTE><font size="1"face="Geneva, Verdana, Arial">code:</font><HR><pre><font size=1 face=courier>

- (<font color = purple>id</font>) awakeFromNib
{

[[NSNotificationCenter defaultCenter] addObserver: <font color = purple>self</font>
selector: <font color = purple>@selector</font> (textDidChange
name:NSControlTextDidChangeNotification
object:textField];

}

</font>[/code]

If you download the code from O'Reilly (yup I got stuck here) you see that same functionality is implemented as:

<BLOCKQUOTE><font size="1"face="Geneva, Verdana, Arial">code:</font><HR><pre><font size=1 face=courier>

- (<font color = purple>id</font>) init
{
<font color = purple>self</font> = [<font color = purple>super</font> init];

[[NSNotificationCenter defaultCenter] addObserver: <font color = purple>self</font>
selector: <font color = purple>@selector</font> (textDidChange
name:NSControlTextDidChangeNotification
object:textField];

<font color = green>return</font> <font color = purple>self</font>;
}


</font>[/code]

So here are my questions:

1. Is this an annoying typo?

2. For this case, why did the latter choose to override "init" as opposed to overriding "awakeFromNib"?

3. Are there any rules of thumb about when to choose one over the other?

Thanks a bunch. By the way, this forum is so freaking good looking and useful. Good job on the renovations!

Cheers

[ 06-09-2001: Message edited by: DaGuy ]

[ 06-09-2001: Message edited by: DaGuy ]

[ 06-09-2001: Message edited by: DaGuy ]
iMac 17" G4 800MHZ & 768 SDRAM
     
Senior User
Join Date: Nov 2000
Status: Offline
Reply With Quote
Jun 9, 2001, 10:08 AM
 
Do what makes more sense to you.

I basically learned everything from Fire. If I remember correctly, Eric uses awakeFromNib to set the intitial state of his GUI widgets and init to load the .nibs and set the owner.

<BLOCKQUOTE><font size="1"face="Geneva, Verdana, Arial">code:</font><HR><pre><font size=1 face=courier>
- (<font color = purple>id</font>)init
{
[<font color = purple>super</font> init];
[[NSBundle mainBundle] loadNibNamed:<font color = orange>@"ourNib"</font> owner:<font color = purple>self</font>];

<font color = brown>// <font color = green>do</font> set up <font color = green>for</font> notifications and anything <font color = green>else</font> not directly connected to the GUI...</font>

<font color = green>return</font> <font color = purple>self</font>;
}

- (<font color = green>void</font>)awakeFromNib
{
NSDictionary *objectPrefs = [<font color = purple>self</font> preferences]; <font color = brown>// imaginary method</font>
[textfield setObjectValue:[objectPrefs objectForKey:<font color = orange>@"textfield"</font>]]; <font color = brown>// textfield is an imaginary outlet</font>

<font color = brown>// set the intial state of any other GUI objects..</font>

}
</font>[/code]

Then, you could use that like..
<BLOCKQUOTE><font size="1"face="Geneva, Verdana, Arial">code:</font><HR><pre><font size=1 face=courier>
FooObject *fooObject = [[FooObject alloc] init];
</font>[/code]
..the bundle would get loaded, the GUI would be setup and you'd be on your way.

But, you could do it all in init, I guess. Or, if it gets automagically created from loading a nib you could do everything in awakeFromNib.
     
DaGuy  (op)
Senior User
Join Date: Oct 2000
Location: Lawrence, KS
Status: Offline
Reply With Quote
Jun 9, 2001, 11:11 AM
 
Thanks for example. I guess the "init" method is not design to unpack Nib files and the "awakeFromNib" is. This leads me to believe that:

(1) "awakeFromNib" can do everything "init" can and more (since it can unpack Nibs).

(2) "awakeFromNib" would never be needed in a GUI-less world. Objects can just be initialized from "init".

I am fairly comfortable with (2) I am a bit shaky on (1). What do you think?

[ 06-09-2001: Message edited by: DaGuy ]
iMac 17" G4 800MHZ & 768 SDRAM
     
Senior User
Join Date: Nov 2000
Status: Offline
Reply With Quote
Jun 9, 2001, 12:11 PM
 
If you make a test-case with a textfield (or whatever) as an Outlet to a class you'll see that init is called before awakeFromNib...

awakeFromNib is just the "all your outlets are connected" notification.
init is the "make me an object" request.

I guess both your assumptions are correct. If you know your class is linked to a nib and won't be created outside that context you could do everything in awakeFromNib and forget about init.
     
DaGuy  (op)
Senior User
Join Date: Oct 2000
Location: Lawrence, KS
Status: Offline
Reply With Quote
Jun 9, 2001, 02:14 PM
 
That makes a sense. I will continue to experiment with these methods but a bit more at ease, now that I know more about their use. Thanks for the clarification.
iMac 17" G4 800MHZ & 768 SDRAM
     
Dedicated MacNNer
Join Date: Jan 2001
Location: Virginia, US
Status: Offline
Reply With Quote
Jun 9, 2001, 05:35 PM
 
Your assumptions are all pretty much on target, but I'll just fill in some in more details in case you're interested.

-init is called at object allocation time (sort of like C++/Java constructors), and typically initializes its instance variables etc. It (or an -initWith* variant) is a fundamental method for any ObjC class (they can be just inherited though).

-awakeFromNib is called by the nib loading architecture on each object created by the nib, plus the passed-in owner object, once all outlets and other connections have been set up and are safe to message.

Obviously, outlets have not been set when -init is called, since the nib loading architecture hasn't had a chance to set them yet (you have to create the object first to set the outlets obviously, and -init is part of the creation process). Thus in the O'Reilly code above, the textField variable is nil at that point. Passing nil to addObserver: ... like that will result in the notification being sent to your object whenever the NSControlTextDidChangeNotification is sent by any object. If this was a demo app with only one textfield in it, then that would be the only time the notification was sent, and so it's likely the author never noticed the problem. It is almost certainly a bug, though it just happened to work.

If your initialization code is just setting some initial values on instance variables and the like, then I would do it in -init, since that's the usual ObjC place for it. Use -awakeFromNib (or alternatives -- see below) for any further setup that needs to be done using other objects loaded from a the nib.

I typically don't use -awakeFromNib in controller-type classes, though there's nothing wrong with doing so. If I need to do initializations after loading the main application nib, I do it in the -applicationDidFinishLaunching: method (in whichever class is the app delegate). For other nibs, my controller classes are almost always subclasses of either NSWindowController or NSDocument, and those classes have -windowDidLoad and -windowControllerDidLoadNib: methods respectively that can be used. All of these methods are called after the -loadNibNamed: method returns, and therefore after -awakeFromNib has been called on all the other objects, so I guess it's just an additional layer of "protection" that everything in the nib is already set up. That's a pretty minor distinction though.

In any event, -awakeFromNib is fine for that kind of stuff, so have at it. [Although in the case of the NSControlTextDidChangeNotification, it may be easier to set the delegate outlet on the NSTextField to your object, as the delegate is automatically set up to be an observer for the notification, calling the -controlTextDidChange: method if it's implemented.]
     
DaGuy  (op)
Senior User
Join Date: Oct 2000
Location: Lawrence, KS
Status: Offline
Reply With Quote
Jun 10, 2001, 11:29 AM
 
Thanks for the details. Whenever I get a break I will do some testing and will post my observations. Be as it may, I think I got the idea behind the two methods. Thanks again
iMac 17" G4 800MHZ & 768 SDRAM
     
   
Thread Tools
Forum Links
Forum Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On
Top
Privacy Policy
All times are GMT -5. The time now is 09:49 PM.
All contents of these forums © 1995-2011 MacNN. All rights reserved.
Branding + Design: www.gesamtbild.com
vBulletin v.3.8.7 © 2000-2011, Jelsoft Enterprises Ltd., Content Relevant URLs by vBSEO 3.3.2