PDA

View Full Version : awakeFromNib v/s InitWithFrame




hoschi
Mar 28, 2006, 11:20 AM
Hi:

I am using an OpenGL view along with an instance of an NSObject as the controller. When I start the program, the control goes first to awakeFromNib in the controller as expected.

I was wondering if its possible to force the control to go to initWithFrame, which is the designated initializer for NSOpenGLView instead of awaekFromNib in NSObject

Thanks



gekko513
Mar 28, 2006, 11:40 AM
Do you mean -initWithFrame:pixelFormat:?

As I understand it, -awakeFromNib is called on every object created in i nib file after all the objects have been inited and had all their connection from Interface Builder set.

And someone else here said that any -init method of the super-classes can also be used to init an object even if it's not mentioned in the docs for that class, so you have to remember to override them all if you have some initing that has to be done.

HiRez
Mar 28, 2006, 12:38 PM
AFAIK, -awakeFromNib: should never be called on an object before its -init: method is called. Are you saying -awakeFromNib: is being called before -initWithFrame: on your NSOpenGLView subclass? That definitely doesn't sound right, although maybe I don't understand exactly what it is you're doing. In any case, you could maybe override +initialize: if you need something done before the Nibs get awakened.

hoschi
Mar 28, 2006, 01:45 PM
The problem is as follows.

I have two classes (each with their own header and implementation files)- one for an NSOpenGLView subclass (I call this glView)and another for an NSObject subclass (I call this controller).

controller has the -(void)awakeFromNib and glView has an -(void)initWithFrame: method.

Now the problem is that when I start the program it goes straight to awakeFromNib and not to initWithFrame.

I temporarily solved the problem by removing the awakeFromNib in the controller and putting it in glView and this seems to work but what I do no understand is why this happened in the first place.

I would appreciate any explanation

Thanks

gekko513
Mar 28, 2006, 02:10 PM
It does some init first. Since you've excluded -initWithFrame:, my guess is that it does -initWithFrame: pixelFormat:, and if not, it would be just a simple init.

HiRez
Mar 28, 2006, 03:09 PM
I think gekko is probably right, check for the -initWithFrame:pixelFormat: initializer. To override that:- (id)initWithFrame:(NSRect)aRect pixelFormat:(NSOpenGLPixelFormat*)aFormat {
if (!(self = [super initWithFrame:aRect pixelFormat:aFormat])) {
return nil;
}

// do your custom initialization here

return self;
}
Now are your objects actually in a nib file? If so, then they should both be receiving awakeFromNib: messages (whether or not you are overriding the method in your subclass).

savar
Mar 28, 2006, 05:23 PM
I temporarily solved the problem by removing the awakeFromNib in the controller and putting it in glView and this seems to work but what I do no understand is why this happened in the first place.

I would appreciate any explanation

Thanks

Hey man--

You're confused and you're confusing other people. Objects in a Nib file have already been instantiated. That means that their init method has already been called. Interface builder then serializes these objects in order to store them on disk. Thats why the method is called "awakeFromNib" and not "initFromNib" -- the objects in the Nib are just "sleeping", but they ARE still there.

Part of what you inherit when you use the Cocoa project template is that Cocoa opens up your nib file, deserializes all of those objects, and then calls awakeFromNib on each one. That means every object in the nib file can have its own copy of that method, and those copies won't interfere with each other.

So...you should probably put awakeFromNib in both your controller and your GLView subclass.

gekko513
Mar 29, 2006, 08:01 AM
Just to get this sorted out once and for all :)
The standard objects on Interface Builder palettes are allocated and initialized when a user interface is built and later are archived when the objects are saved to a nib file. When the nib file is unarchived, these objects are restored. If you create a custom subclass based on the class for a standard palette object, Interface Builder encodes the superclass when it archives the object but has the custom class swapped in when the object is unarchived. In either case, the initializer for the unarchived object is not called. However, if you have a custom class of NSView (represented by the Custom View palette object), the initializer of the class is called when the Custom View object is unarchived. In any case, the application sends each custom class associated with a nib file an awakeFromNib message when all objects in a nib file have been unarchived; this message gives the class an opportunity to establish connections or perform any other set-up tasks.
Link (http://developer.apple.com/documentation/Cocoa/Conceptual/CocoaFundamentals/CoreAppArchitecture/chapter_7_section_8.html)

hoschi
Mar 29, 2006, 01:41 PM
Thanks for the explanations.

I have a program where I have an -(void)awakeFromNib method for the controller class and an -(id)initWithFrame:(NSRect)frameRect method for the openGL class. When I run the program the control goes to the -(id)initWithFrame:(NSRect)frameRect method.

Recently I wrote another program but in that case the control goes to the -(void)awakeFromNib first.

So my question is:

1. What decides as to where the control is going to go first.
2. How can I force the control to go first to controller or to openGL view incase both of them have awakeFromNib's or both of them have their designated initialization methods.

Thanks a ton in Advance
Vyom

gekko513
Mar 29, 2006, 01:51 PM
Are you absolutely positively sure that it doesn't go to -initWithFrame:pixelFormat:?

As for the other question, using +initialize ...

ClassA.m

static BOOL inited = NO;
@implementation ClassA
+ (void) initialize {
if (inited==NO) {
inited = YES;
...
}
}
...

ClassB.m

static BOOL inited = NO;
@implementation ClassB
+ (void) initialize {
if (inited==NO) {
inited = YES;
[ClassA initialize];
...
}
}
...

This ensures that ClassA initializes before ClassB. You can use similar mechanisms with -awakeFromNib to make sure something always happens before something else.

hoschi
Mar 29, 2006, 02:03 PM
[QUOTE=gekko513]Are you absolutely positively sure that it doesn't go to -initWithFrame:pixelFormat:?

Yes. I rechecked it, and it does not go to the initWithFrame:pixelFormat: method.

Thanks for the other part though.