On Jan 10, 2011, at 4:17 PM, Phil Hystad wrote:

> Is there a proper way to initialize a view controller.  So far, I have been 
> doing this in the application delegate by calling calling an initialize 
> method ( i.e. [viewController initialize]) in 
> application:didFinishLaunchingWithOptions: method (prior to the view being 
> added to the window and the window made visible).


*** Important ***
+(void)initialize is a class method which the runtime sends to the class 
exactly once just before any of this class' method is invoked, and any of its 
super class if +initialized has not yet been invoked.
You rarely need to override +initialize -- and you never call it yourself!



But yes, there is a proper way to do initialization of a view controller object 
:)  There are lots of examples of how you should do this within the iOS or Mac 
OS X documentation.

Basically, when you load your view from a nib you will override these methods 
in order to initialize a view controller:

-viewDidLoad
        This method is called regardless of whether the views were stored in a 
nib file or created 
        programmatically. You usually override it to do additional setup after 
the view has been 
        loaded from a nib.
        If you override -viewDidLoad you may want to override -viewDidUnload 
accordingly, which is the          "counterpart" of -viewDidLoad.
      

-awakeFormNib 
        To do additional setup after the view has been loaded from a nib. You 
often can do all your setup
        in viewDidLoad, but sometimes this seems a better place. At the time 
the method is invoked,
        outlet and action connections are already established.


In the cases where you want to create the controller's view yourself 
programmatically, you have to use
-loadView. If you do so, you need to create the view hierarchy and assign the 
root view to the view property of the controller.


You must not call any of these methods yourself! The framework will do this for 
you when it is appropriate.


An example might be useful:

The following code assumes you have a nib where you load the view:

@interface MyViewController : UIViewController {
  IBOutlet UIView* mySpecialSubView;
  NSArray* myArray;
}

@property (retain) UIView* mySpecialSubView;
@property (retain) NSArray* myArray;

@end

@implementation
@synthesize mySpecialSubView;
@synthesize myArray;

- (void) viewDidLoad
{
    [super viewDidLoad];  // always invoke super!

    // In debug mode, you might check here whether you have established the 
links for your outlets in IB:
    NSAssert(mySpecialSubView, @"IBOutlet 'mySpecialSubView' is nil"); // 
forgot to setup the link in IB?

    // configure my view unless this is already done in IB:
    self.view.backgroundColor = [UIColor blackColor];

    // do other setup, for instance setting up a navigation bar, navigation item
    ...

    // if your view controller needs to initialize other ivars, you might 
initialize them here, 
    // or do "lazy initialization" (see below)
    ...

    // Note, that viewDidLoad will be called *everytime* the view gets reloaded 
from
    // the resource!
    // Sometimes, you explicitly DON'T want to perform certain initialization 
steps again 
    // after the view will be reloaded. In this case, use a flag as an ivar 
which determines 
    // whether you have done these initialization steps:
    if (!isInitialized) {
        [self setupOnce];
        isInitialized = YES;  // this is an ivar
    } 
}


You have to override -viewDidUnload in certain cases, e.g.:

- (void) viewDidUnload {
    self.mySpecialSubView = nil;    // Outlets shall be set to nil!

    // optionally, you might want to release myArray - just in order to safe 
memory. But
    // this depends on your needs, and often you explicitly don't want the 
array to be
    // recreated after a reload of the view. 
    self.myArray = nil; // optionally
}



// lazy initialization - this overrides the getter method which was otherwise 
defined
// by the @synthesize directive:
- (NSArray*) myArray {
    if (myArray == nil) {
        myArray = [NSArray alloc] init... ];
    }
    return myArray;
}


// don't forget to release ivars if required:
-(void) dealloc {
    [mySpecialSubView release], mySpecialSubView = nil;
    [myArray release], myArray = nil;
    [super dealloc];  // always invoke super (at the last statement)
}



One thing you should care of:
-viewDidLoad and -awakeFormNib, as well as -loadView may be called more than 
once for the lifetime of the view controller. So, be carefully not to 
initialize ivars in such a way that you get a memory leak. The following code 
snippet would be the wrong way:

- (void) viewDidLoad {
    [super viewDidLoad];    
    myArray = [[NSArray alloc] init...];    // possibly memory leak!
}

The way to do proper initialization would leverage properties:
- (void) viewDidLoad {
    [super viewDidLoad];
    NSArray* tmp = [[NSArray alloc] init...];
    self.myArray = tmp;  // property retains
    [tmp release], tmp = nil;
}

However, when the view is reloaded (once it has been unloaded for some reason), 
the array will be initialized again! This may or may not have undesired side 
effects since the array will be released and initialized again. So, lazy 
initialization may be the preferred way for certain ivars.



Regards,

Andreas


> 
> However, I am not sure if this is the Cocoa canonical way of doing things.  
> By the way, this example comes from UIKit but the same question would apply 
> to any OS X Cocoa application too.
> 
> phil
> phys...@mac.com
> 
> _______________________________________________
> 
> Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)
> 
> Please do not post admin requests or moderator comments to the list.
> Contact the moderators at cocoa-dev-admins(at)lists.apple.com
> 
> Help/Unsubscribe/Update your Subscription:
> http://lists.apple.com/mailman/options/cocoa-dev/agrosam%40onlinehome.de
> 
> This email sent to agro...@onlinehome.de

_______________________________________________

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Reply via email to