Это мой шаблон:
1) SpecialView создает MessageView и содержит в нем сильную ссылку.
2) Пользователь нажимает кнопку в MessageView, что приводит к его исчезновению.Затем MessageView сообщает своему делегату SpecialView, что он полностью исчез.
3) SpecialView выпускает MessageView.
Проблема заключается в следующем:
- (void)fadedOut:(NSString*)animationID finished:(NSNumber*)finished context:(void*)context {
[self.delegate messageViewFadedOut:self]; // delegate releases us...
// self maybe got deallocated... BOOM!
// now what? method of a zombie returns? stack freaks out?
} // does it even return?
В последней строкеЯ звоню делегату, который, в свою очередь, немедленно освобождает MessageView.-fadedOut: finish: context: вызывается с помощью основного анимационного обратного вызова didStopSelector.
Боюсь, что экземпляр MessageView будет освобожден непосредственно перед тем, как -fadedOut: закончен: контекст: полностью возвращен,вызывая очень неприятные случайные ошибки
Когда-то старый программист-ветеран сказал мне: «Никогда не руби ветку, на которой ты сидишь».
Так, чтобыУбедитесь, что экземпляр сохранился до тех пор, пока этот метод не вернется. Я сделал retain-autorlease-dance перед вызовом делегата:
- (void)fadedOut:(NSString*)animationID finished:(NSNumber*)finished context:(void*)context {
//[[self retain] autorelease];
[self.delegate messageViewFadedOut:self]; // delegate releases us...
}
Однако в ARC танцы retain-autorelease больше не разрешены (инструмент миграции выигралне позволяют), и, кажется, нет никакого способа заставить систему ARC сделать что-то подобное.
Поэтому я придумал эту стратегию вместо этого:
- (void)fadedOut:(NSString*)animationID finished:(NSNumber*)finished context:(void*)context {
[self.delegate performSelector:@selector(messageViewFadedOut:) withObject:self afterDelay:0];
}
Отсроченный executeSelectorнадеюсь, что метод полностью вернется.Насколько я знаю, задержка в 0 все еще гарантирует, что селектор будет выполнен в следующей итерации цикла выполнения, а не сразу.
Есть большая вероятность, что это тоже фальшивка.
Как можноЯ правильно разрешаю эту проблему с одним объектом, прося другой уничтожить последнюю ссылку на него с вероятностью того, что объект get будет освобожден до того, как метод, который сделал вызов другому объекту, получит шанс полностью вернуться?Может ли быть что-то вроде стека трассировки зомби?
И как мне решить что-то подобное под ARC?