В основном ответом на подобные вещи является не показывать компоненты ваших представлений через контроллер представлений, поскольку другие объекты, вероятно, не должны получать к ним доступ. Итак, если ваш контроллер представления управляет видом, который отображает имя человека, например, вместо того, чтобы делать что-то вроде этого:
PersonNameController* pnc = [[PersonNameController alloc] initWithNibName:nil bundle:nil];
[[pnc nameLabel] setText:@"Jason"];
[[self navigationController] pushViewController:pnc animated:YES];
Вы должны отделить биты данных / модели от битов представления и выставить свойство 'name' на вашем контроллере представления. Тогда вы можете получить этот простой пример кода, который всегда работает должным образом (он требует немного больше кода, но он избавляет вас от таких головных болей и, если быть совершенно честным, это то, чем занимается MVC):
PersonNameController* pnc = [[PersonNameController alloc] initWithNibName:nil bundle:nil];
[pnc setName:@"Jason"];
[[self navigationController] pushViewController:pnc animated:YES];
И реализация такого контроллера:
@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's 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's 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
Краткое примечание: это было просто напечатано в этом маленьком окошке, и я очень устал, поэтому он не проверяется на общую правильность синтаксиса и т. Д. Он предназначен в качестве быстрого примера, а не что-то вырезать наклеить.
Кроме того, если у вас есть несколько свойств, которые необходимо обновлять каждый раз, вы можете создать один метод утилиты, например -udpateLabels, или что-то, что обновит их все. Затем вы вызываете это из каждого сеттера и из viewDidLoad или loadView. Таким образом, вы будете иметь все в одном месте (за счет некоторой производительности). Если после профилирования вы тратите слишком много времени на этот метод, вы можете использовать его соответствующим образом.