Беда со свойствами в Objective-C - PullRequest
1 голос
/ 23 сентября 2011

У меня проблемы с назначением экземпляра класса следующему подклассу UITableViewController:

@interface MyTableViewController : UITableViewController </*usual protocols*/>
@property (nonatomic, retain) MyClass *myClass;
@end

В настоящее время я назначаю ненулевой экземпляр MyClass экземпляру MyTableViewController, например:

MyTableViewController *myTableViewController = [[MyTableViewController alloc] init];
MyClass *nonNullInstanceOfMyClass = [[MyClass alloc] init];

myTableViewController.myClass = nonNullInstanceOfMyClass;

[self.navigationController pushViewController:myTableViewController animated:YES];

[nonNullInstanceOfMyClass release];
[myTableViewController release];

Проблема в том, что myClass null в MyTableViewController viewDidLoad. Почему это происходит?

Редактировать # 1 : Я проверяю, что nonNullInstanceOfMyClass не является нулевым, NSLogging его.

Редактировать # 2 : Предоставлено больше кода. Также viewDidLoad, кажется, вызывается до того, как я нажимаю контроллер представления (что может вызвать проблему ... хотя это кажется странным).

Редактировать # 3 : исправлено путем перемещения self.tableView.delegate = nil; и self.tableView.dataSource = nil; из init в viewDidLoad.

Ответы [ 3 ]

0 голосов
/ 23 сентября 2011

viewDidLoad запускается, когда представление загружается из xib.

У вас есть несколько вариантов здесь.

Простейшим является viewDidAppear: метод

- (void)viewDidAppear:(BOOL)animated
{
    // Handle what you want for when your view has become visible. 
    // This may happen more then once. So a flag for the first time will
    // give you a sufficient Limit for Initialization
}

или тамis viewWillAppear:

Другой вариант - заставить IB загрузить для вас класс таким образом, чтобы он не был нулевым.И будет доступен в viewDidLoad:

Ваш MyClass должен быть UIView.

Вы помещаете UIView (в качестве заполнителя) в View TableViewController, где вы хотите его.

Затем вы устанавливаете его тип класса в Интерфейсном Разработчике в Инспекторе Идентификаций под Пользовательским Классом.

Наконец, вы перетаскиваете соединение из IBOutlet

@property (nonatomic, retain) IBOutlet MyClass *myClass;

в ваш Пользовательский КлассUIView в Интерфейсном Разработчике

Затем, когда Интерфейсный Разработчик инициализирует ваш класс, он заполнит это свойство пустым экземпляром этого класса.

Третьим вариантом будет свойство отложенной загрузки

Вот как я делаю ленивую загрузку

//we will take for granted that your @property is in the header
//and the following Synthesize is on the class
@synthesize myClass=_myClass; // setting instance variable to avoid confusion 
- (MyClass*) myClass
{
    if (_myClass == nil) _myClass = [[MyClass alloc] init];//Create a default instance and retain it
    return _myClass;
}

, затем вы используете self.myClass и ваш метод получения создаст его для вас.

РЕДАКТИРОВАТЬ:

Я добавил = _myClass в @synthesize, чтобы изменить переменную экземпляра вне свойства

. Таким образом, использование myClass вызовет ошибку, и вы будете вынуждены использовать self.myClass для получения средства доступа к свойству.

0 голосов
/ 23 сентября 2011

Измените следующую строку с:

@property (nonatomic, retain) MyClass *myClass;

на:

@property (nonatomic, assign) MyClass *myClass;
0 голосов
/ 23 сентября 2011

Делаете ли вы что-нибудь между созданием контроллера представления и присвоением свойству?viewDidLoad не обязательно вызывается, когда вы помещаете контроллер представления в стек навигации - он вызывается всякий раз, когда ему нужно загрузить представление.Так, например, NSLog(@"%@", myTableViewController.view); вызовет viewDidLoad, и если вы сделали это до присвоения свойству, это объяснило бы это поведение.

Не могли бы вы опубликовать фактический код вместо приблизительного значения, пожалуйста?Там могут быть важные детали, которые вы опускаете.

...