Делегаты - сохранить или назначить - освободить?
Я видел несколько сообщений, связанных с делегатами, и я хотел бы знать правильный способ их ссылки. Предположим, что у меня есть объект, объявленный как:
@interface MyViewController : UITableViewController {
id delegate;
}
@property (nonatomic, retain) id delegate;
@end
Через жизненный цикл MyViewController
он будет обращаться к методам своего делегата в ответ на взаимодействие с пользователем.
Когда нужно избавиться от экземпляра MyViewController
, нужен ли delegate
ivar release
в методе реализации dealloc
, поскольку он объявлен с помощью retain
?
Или наоборот, должен ли delegate
быть сохранен? Возможно, это должно быть @property (nonatomic, assign) id delegate
? Согласно Apple docs:
сохранить... Обычно этот атрибут используется для таких скалярных типов, как NSInteger и CGRect, или (в среде с подсчетом ссылок) для объектов, которые у вас нет, таких как делегаты.
Обычно я просто согласен с тем, что говорят документы, но я видел много кода, который вызывает retain
в делегате. Это просто "плохой код"? Я откладываю здесь экспертов... Каков правильный способ справиться с этим?
Ответы
Ответ 1
Как правило, вы хотите назначить делегатов, а не сохранять их, чтобы избежать круговых удерживаемых отсчетов, когда объект A сохраняет объект B, а объект B сохраняет объект A. (Вы можете видеть, что это называется сохранением "слабой ссылки" на делегат.) Например, рассмотрим следующий общий шаблон:
-(void)someMethod {
self.utilityObject = [[[Bar alloc] init] autorelease];
self.utilityObject.delegate = self;
[self.utilityObject doSomeWork];
}
если свойства utilityObject
и delegate
объявлены с помощью retain
, тогда self
теперь сохраняет self.utilityObject
и self.utilityObject
сохраняет self
.
См. Почему делегатам Objective-C обычно присваивается присваивание свойства вместо сохранения? для получения дополнительной информации об этом.
Если вы назначаете делегата, а не сохраняете его, вам не нужно беспокоиться о его освобождении в dealloc.
Ответ 2
Обычно это указывает на плохой дизайн, поскольку большинство делегатов сохраняют свои объекты (создавая потенциал для сохранения циклов и, следовательно, утечек.) Но есть случаи, когда объект должен сохранять свой делегат. Обычно это случаи, когда ссылка на объект недоступна, поэтому делегат не может сохранить его, но сам по себе может указывать на плохой дизайн.
Ответ 3
Я тоже много слышал об этом. Я не знаю правильного пути, но я могу сказать вам, что я достиг в своей работе.
Вы хотите retain
все, что вам нужно, чтобы сохранить свой дескриптор. То, что все владение, в среде с подсчетом ссылок. Это выражение, что "мне нужно это позже, не позволяйте этому уйти от меня".
Это ТАКЖЕ означает, что вы несете ответственность за освобождение своей претензии. Если вы этого конкретно не делаете, вы склонны к различным проблемам, но особенно имеете дело с делегатами, которые вполне могут сохранить объект, которым они являются делегатом. Если вы не занимаетесь удержанием делегата, владение будет циклическим, и объекты будут течь. Но не забудьте освободить то, что вы сохраните, и со мной все будет в порядке.