I am trying to subclass NSOutlineView. Here is my code:
OutlineViewSublcass.h:
#import <Cocoa/Cocoa.h> @interface OutlineViewSubclass : NSOutlineView { } @end
OutlineViewSubclass.m:
#import "OutlineViewSubclass.h" @implementation OutlineViewSubclass - (id)initWithFrame:(NSRect)frame { self = [super initWithFrame:frame]; printf("debug A\n"); return self; } - (void)awakeFromNib { printf("debug B\n"); } @end
The debug output is:
debug B
Why isn't (id)initWithFrame:(NSRect)frame
being called?
The commonly recommended place to do custom initialization for custom views is in the initWithFrame or initWithCoder methods. When you are defining parts of your UI in IB, initWithCoder is the one of these that is called by the nib-loading code.
The nib-loading infrastructure sends an awakeFromNib message to each object recreated from a nib archive, but only after all the objects in the archive have been loaded and initialized. When an object receives an awakeFromNib message, it is guaranteed to have all its outlet and action connections already established.
Official Apple answer for this is Creating a Custom View.
View instances that are created in Interface Builder don't call initWithFrame: when their nib files are loaded, which often causes confusion. Remember that Interface Builder archives an object when it saves a nib file, so the view instance will already have been created and initWithFrame: will already have been called.
The awakeFromNib method provides an opportunity to provide initialization of a view when it is created as a result of a nib file being loaded. When a nib file that contains a view object is loaded, each view instance receives an awakeFromNib message when all the objects have been unarchived. This provides the object an opportunity to initialize any attributes that are not archived with the object in Interface Builder.
Cocoa controls implement the NSCoding protocol for unarchiving from a nib. Instead of initializing the object using initWithFrame: and then setting the attributes, the initWithCoder: method takes responsibility for setting up the control when it's loaded using the serialized attributes configured by Interface Builder. This works pretty much the same way any object is serialized using NSCoding.
It's a little bit different if you stick a custom NSView subclass in a nib that doesn't implement NSCoding, in that case initWithFrame: will be called. In both cases awakeFromNib will be called after the object is loaded, and is usually a pretty good place to perform additional initialization in your subclasses.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With