Если вы установите делегат на нуль в классе с помощью делегата или самого класса
Если класс A использует класс B, а класс A является делегатом класса B, нормально ли, если делегат установлен в nil в классе B dealloc? Я видел, что код обычно сбросил делегат на нуль внутри класса A dealloc, но не был уверен, что реальная разница делает это так или иначе.
например. Это обычный способ:
// somewhere in class A
- (void) someFunc {
self.b = [[B alloc] init];
self.b.delegate = self;
}
- (void) dealloc {
self.b.delegate = nil;
[self.b release];
}
Ответы
Ответ 1
Да, вы должны установить свойство delegate класса B равным нулю в classA dealloc.
Это не проблема управления памятью, потому что свойства делегата должны быть отмечены как назначаемые, а не сохраняемые, чтобы избежать циклов сохранения (иначе dealloc никогда не будет вызываться). Проблема в том, что иначе classB может передать класс сообщения A после его освобождения.
Например, если классB имеет вызов delagate, чтобы сказать "быть скрытым", а classB освобождается сразу после класса A, он будет сообщать об уже отлученном классе A, вызывающем сбой.
И помните, вы не всегда можете гарантировать порядок dealloc, особенно если они автореализовываются.
Итак, да, нуль из свойства делегата в classA dealloc.
Ответ 2
Насколько мне известно, его наилучшая практика (назначить) делегата, чтобы вы избегали циклических ссылок на учетные записи для ситуаций, подобных этому. Если вы правильно настроили свойство, то есть:
@property (assign) id<BDelegate> delegate;
Вам не нужно выполнять какое-либо управление памятью в dealloc, так как счет сохранения не набит, когда вы вызываете self.b.delegate = self; - в отличие от использования (сохранения) или (копирования)
Имеют смысл? Было бы неплохо установить делегат на нуль, но в чем смысл?
Ответ 3
Во-первых, несколько наблюдений...
- Вы забыли позвонить
[super dealloc]
в конце своего собственного метода dealloc.
- Поскольку "a" создан "b", и если никакие другие объекты не сохранили "b", нет смысла в деле делегирования делегата в
-dealloc
, так как "b" все равно будет уничтожено. Если возможно, что другие объекты имеют ссылку на "b" (что означает, что он может пережить "a" ), установите делегат на нуль.
- Объектом 'b' должен быть тот, кто позаботится о своем делетете в своем собственном -dealloc, если это необходимо. (Как правило, делегат не сохраняет делегата.)
- Избегайте использования свойств в -init... и -dealloc-методах - Apple отпугивает это и не без оснований. (Не только это может иметь неожиданные побочные эффекты, но также может вызвать более неприятные, более сложные проблемы.)
- Использование свойств (через синтаксис точек), когда вам не нужно невидимо добавлять дополнительную работу. Например,
self.b.delegate = self
эквивалентен [[self getB] setDelegate:self]
- это просто синтаксический сахар, который делает его похожим на то, что вы напрямую обращаетесь к ivar, но на самом деле нет.
- Использование свойств без понимания того, что они делают, может привести к проблемам. Если
self.b
сохраняет значение (для свойства задано значение "назначить" ), у вас есть утечка памяти на ваших руках.
Вот как я, вероятно, напишу его:
- (void) someFunc {
b = [[B alloc] init];
b.delegate = self; // or [b setDelegate:self];
}
- (void) dealloc {
b.delegate = nil;
[b release];
[super dealloc];
}