Basically, the answer to this question is not to expose the components of your views through your view controller, since other objects probably shouldn't access them. So, if your view controller controls a view that, for example, displays a personβs name, instead of doing something like this:
PersonNameController* pnc = [[PersonNameController alloc] initWithNibName:nil bundle:nil]; [[pnc nameLabel] setText:@"Jason"]; [[self navigationController] pushViewController:pnc animated:YES];
You separate the data / model bits from the view bits and output the 'name' property to your view controller. Then you can get this simple example code that always works correctly (it requires a bit more code, but it saves you headaches like this and, to be honest, this is what MVC is talking about):
PersonNameController* pnc = [[PersonNameController alloc] initWithNibName:nil bundle:nil]; [pnc setName:@"Jason"]; [[self navigationController] pushViewController:pnc animated:YES];
And the implementation of such a controller:
@interface PersonNameController : UIViewController { @private NSString* name_; } // other people use this to pass model data to the controller @property(nonatomic,copy) NSString* name; @end @interface PersonNameController() // for us only @property(nonatomic,assign) UILabel* nameLabel; @end @implementation PersonNameController // properties @synthesize nameLabel; @synthesize name = name_; - (void)setName:(NSString*)value { if( [value isEqualToString:name_] ) return; [name_ autorelease]; name_ = [value copy]; [[self nameLabel] setText:name_?:@""]; } // view lifecycle - (void)loadView { // ob fake frame for now UIView* view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)]; UILabel* label = [[UILabel alloc] initWithFrame:CGRectMake( 10, 10, 300, 37)]; [view addSubview:label]; [self setView:view]; [self setNameLabel:label]; // Set the name on the label if one set already [label setText:name_?:@""]; // clean up [view release]; [label release]; } // take care of unloads - (void)viewDidUnload { // no need to release, but set nil so it not used while the view // is unloaded nameLabel = nil; [super viewDidUnload]; } - (void)dealloc { // nameLabel is assign (owned by our view) so we don't release here // but set to nil just to be good citizens nameLabel = nil; [name_ release]; [super dealloc]; } @end
Quick note: it was just printed in this small box, and I was really tired, so he did not check the complete syntax, etc. This meant as a quick example, not something to cut and paste.
In addition, if you have several properties that need to be updated each time, you can create one utility method, such as -udpateLabels, or something that updates all of them. Then you call this from each setter and from viewDidLoad or loadView. Thus, you will have everything in one place (due to some performance). If after profiling you spend too much time in this method, you can break it down as needed.