Проверка правильности объекта делегата перед отправкой ему сообщения - PullRequest
3 голосов
/ 22 сентября 2009

Я пытаюсь реализовать шаблон делегата в Objective-C, однако я испытываю исключение Bad Access при вызове делегата иногда. Кажется, это вызвано освобождением делегата. Apple не рекомендует удерживать делегатов.

Как я могу проверить своего делегата, если он все еще действителен, прежде чем пытаться отправить ему сообщение?

Ответы [ 4 ]

8 голосов
/ 22 сентября 2009

Если есть вероятность, что делегат освободит делегата, значит, что-то не так с вашим дизайном. Вы должны устанавливать делегаты только для объектов, у которых продолжительность жизни короче, чем у самого делегата. Например, установка делегата в подпредставлении / контроллере - это хорошо, потому что подпредставление / контроллер имеет меньшую продолжительность жизни, чем вызывающий.

AFAIK, нет надежного способа определить, был ли объект уже выпущен.

3 голосов
/ 22 сентября 2009

То, что Apple имеет в виду, не оставляя делегатов, состоит в том, что объекты не должны сохранять своих делегатов, потому что они не владеют ими. Это только объекты, которые обрабатывают сообщения.

Это не значит, что вы вообще не должны оставлять делегатов. Объект, который создает делегат, должен владеть им. В контексте не-GC-приложений это означает, что он должен обрабатывать цикл сохранения и выпуска, а для GC-приложений это означает, что объект контроллера сохраняет указатель на делегат в iVar.

не видя какой-либо код или сообщение об ошибке, трудно найти корень этой проблемы.

1 голос
/ 19 июня 2011

Я также хотел бы поделиться своим опытом, который очень похож на опыт Нико.

Я работал с модифицированным примером LazyTablesCode, который является примером, полученным непосредственно от Apple и загружающим изображения в UITableView асинхронно. Связь между загрузчиком и просмотром через делегатов.

В моем коде у меня была проблема, что иногда загрузка изображения заканчивается, когда форма, которая должна быть вызвана через делегата, была освобождена. Я был вынужден добавить этот кусок кода внутри кода viewController (метод dealloc):

if (self.nsDictionaryWithObjectsDownloading != nil) {
    for (id theKey in self.nsDictionaryWithObjectsDownloading) {
        Myobj *downloader = [self.nsDictionaryWithObjectsDownloading objectForKey:theKey];
        downloader.delegate = nil;
    }
}

Кажется, что эти строки решают проблему. В любом случае, было бы очень признательно за то, что это хорошее решение или нет, или даже о проблемах с памятью при выполнении downloader.delegate = nil;

Спасибо и привет,

1 голос
/ 30 октября 2009

В приложении для просмотра фотографий я использую асинхронный http для загрузки изображений; бывает, что пользователь часто отклоняет текущее представление (на которое ссылается мой асинхронный http-объект через делегата) до завершения загрузки http, вызывая BAD_ACCESS при вызове метода делегата контроллера представления. Я решил это, установив .delegate в ноль внутри блока dealloc контроллера вида

...