views:

99

answers:

3

If I have a custom NSObject class called ProgramModel, does it get alloc/init -ed when I @property and @synthesize it from another class? For instance, in a ProgramController class like this

// ProgramController.h
#import "ProgramModel.h"
@interface ProgramController : UIViewController {
    ProgramModel *programModel;
}
@property (nonatomic, retain) ProgramModel *programModel;

// ProgramController.m
#import "ProgramController.h"
@implementation ProgramController
@synthesize programModel;
// etc

Do I also need to alloc/init in the initWithNibName or viewDidLoad, or is it already alloc/init-ed because of the property/synthesize?

+3  A: 

You need to populate the property manually. The exception is if you have an IBOutlet property that you've connected in a nib file; that will get populated automatically when the nib is loaded.

I find that for view controllers the vast majority of properties are IBOutlets and properties that describe what the view will show, and the latter case is usually set by the object that creates the view controller. That will usually be the case for a view controller that shows a detail view for some object.

If you do have properties that are completely local to the view controller, a common pattern is to write your own getter and setter (rather than using @synthesize) and create the object in the getter if it doesn't exist. This lazy-loading behavior means you can easily free up resources in low-memory conditions, and that you only pay the cost of loading an object when you need it.

// simple lazy-loading getter
-(MyPropertyClass*)propertyName {
    if(propertyIvarName == nil) {
        propertyIvarName = [[MyPropertyClass alloc] init];
        // ... other setup here
    }
    return propertyIvarName;
}
Seamus Campbell
*technically* the outlet is `nil` until the nib is loaded, which (in the case of NSWindow/ViewController) won't happen until you invoke `[controller window]` or `[controller view]`.
Dave DeLong
I'm not sure what the distinction you're drawing is here. I did say "when the nib is loaded"...
Seamus Campbell
@Seamus yes, i just wanted to clarify that loading the nib doesn't necessarily happen during initialization. i've gotten bitten so many times by trying to access outlets that weren't there because i hadn't loaded the nib yet.
Dave DeLong
-1 It is often more approperiate to assign properties in `-init`, since `-viewDidLoad` can be called multiple times throughout the object lifecycle, and the view might not be immediately loaded. A "model" property should definitely be tied to the controller's lifetime, not the view's lifetime.
tc.
@tc. updated to reflect common usage patterns. Better?
Seamus Campbell
Lazy loading is only worthwhile for things that use a significant amount of memory, of course ;)
tc.
+3  A: 

By default, all instance variables are zero'd out. In the case of objects, that means they're nil. If you want an initial value in the property, you need to put it there during your initializer/viewDidLoad method.

Dave DeLong
A: 
  • @property only declares the getter/setter methods.
  • @synthesize only generates the accessors for you.

They are not automatically assigned values, apart from the memory being zeroed. Additionally, you have to set them to nil in -dealloc to avoid a leak.

It also doesn't make sense to "alloc a property". An object property is a pointer. (And think of what happens if you have a linked list class...)

(N.B.: The property attributes also affect the @synthesized method, and the properties are also known to the runtime; see class_copyPropertyList() and friends.)

tc.