2009-09-22 6 views
3

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

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

ответ

8

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

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

+0

Чтобы увидеть, если объект был выпущен полностью - отправить сообщение войти либо '' dealloc' или finalize' методов класса. – Abizern

+0

@ Абизем: в этом случае это не поможет. Вопрос в том, можно ли определить, был ли объект выпущен (освобожден). Я не думаю, что это возможно вообще без сотрудничества с самим объектом. –

+0

Я имел в виду, что класс отправляет сообщения журнала, когда он полностью освобождается. – Abizern

3

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

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

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

1

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

+0

Возможно, вы захотите отменить и освободить асинхронный объект загрузки HTTP, особенно если ваше приложение предназначено для iPhone. Рецензенты App Store не относятся к чрезмерному использованию полосы пропускания, например, когда ваше приложение продолжает загружать изображение после того, как пользователь уже отказался от него. В идеале сохраните частичный файл в каталоге временных файлов и возобновите загрузку, если пользователь вернется к изображению. –

1

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

Я работаю с модифицированным примером 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;

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

+0

Я нашел, что делегат не стал лучшим практическим ответом. Однако у Филиппа есть очень хорошие моменты. –

Смежные вопросы