As Jeremie Wekdin mentioned that, my question is somehow duplicated. The similar question and answers do reveal that in case of nib/xib file being used, there is memory issue to be considered.
In short, Cocoa will look for setOutletName first, and use the property method to set UI control object; otherwise, Cocoa will direct set to the class member variable and retain it. That means the filed object should be released in dealloc method.
That's fine. However, in case of my question, my field variable has different name from its corresponding property name, like _firstName and firstName. In this case, I think that Cocoa is not smart enough to figure out the property method and object retrieved from nib/xib is directly set to the class member.
To verify it, I overwrite the setter:
// in .m file
@implementation MyViewController {
@synthetic firstName = _firstName;
- (void) setFirstName:(UILabel*) value {
NSLog("_firstname: %@", _firstName);
[_firstname autorelease];
_firstName = [value retain];
}
Then I load my view, the log message does not show in the XCode's output console. However, if I keep the variable name and property name the same. I do see the setter is called:
// in .h
@interface MyViewController : UIViewController {
IBOutlet UILabel* firstName;
...
}
@property (nonatomic, retain) UILabel* firstName;
...
@end
// in .m file
@implementation MyViewController {
@synthetic firstName;
- (void) setFirstName:(UILabel*) value {
NSLog("firstName: %@", firstName);
[firstName autorelease];
firstName = [value retain];
}
...
@end
In the output console, when the view shows, I see:
firstName: (null)
As the duplicated QA suggested, I read the Appl's Resource Programming Guide. Find the document in the section The Nib Object Life Cycle, The Object Loading Process, and #3 Outlet connection. You should see that Mac OS X and iPhone OS have different ways to connect outlet to objects. "In iPhone OS, the nib-loading code uses the setValue:forKey: method to reconnect each outlet"
So I tried the following codes:
@implementation MyViewController {
@synthetic firstName = _firstName;
- (void) setValue:(id) value forKey:(NSString*) key {
NSLog("forKey: %@; value: %@", key, value);
if ([key isEqualToString:@"_firstName"])
// It should then call the accessor or property
// self._firstName = value;
// to set value, like the follow codes in the setter:
[_firstName autorelease];
_firstName = [value retain];
}
...
}
...
@end
I recompiled my code again and I did see all the property setter calls, including the key _firstName. Continued from Apple's doc:
"That method (setValue:forKey:) similarly looks for an appropriate accessor method and falls back on other means when that fails."
This explains why in my case(property name is different from outlet variable name) the property is called by Cocoa.
In conclusion, there is a memory issue when IBOutlet and nib/xib are used (as a way to load views) for a field control. It would be nice to let Cocoa to find out a defined accessor or property to set a field variable, which handles retaining objects. If you define a property for an IBOutlet field variable, both should have the same. As a result, the codes will work in both Mac OS X and iPhone OS.