У меня объективный класс C. В нем я создал метод инициализации и настроил в нем NSNotification
//Set up NSNotification
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(getData)
name:@"Answer Submitted"
object:nil];
Где мне установить [[NSNotificationCenter defaultCenter] removeObserver:self]
в этом классе? Я знаю, что для a UIViewController
я могу добавить его в viewDidUnload
метод. Итак, что нужно сделать, если я только что создал целевой класс c?
-(void)dealloc
а затем добавитьremoveObserser:self
в него. Это наиболее рекомендуемый способ поставитьremoveObservers:self
dealloc
метод в iOS 6?Ответы:
Общий ответ будет «как только вам больше не нужны уведомления». Это явно не удовлетворительный ответ.
Я бы порекомендовал вам добавить вызов
[notificationCenter removeObserver: self]
в методdealloc
тех классов, которые вы собираетесь использовать в качестве наблюдателей, так как это последний шанс полностью отменить регистрацию наблюдателя. Однако это защитит вас только от сбоев из-за уведомления центра уведомлений о мертвых объектах. Он не может защитить ваш код от получения уведомлений, когда ваши объекты еще не находятся / больше не находятся в состоянии, в котором они могут правильно обрабатывать уведомление. Для этого ... См. Выше.Изменить (поскольку ответ, похоже, вызывает больше комментариев, чем я мог подумать) Все, что я пытаюсь сказать здесь, это: действительно сложно дать общий совет относительно того, когда лучше всего удалить наблюдателя из центра уведомлений, потому что это зависит от:
Итак, лучший общий совет, который я могу дать: защитите свое приложение. против хотя бы одного возможного отказа, сделайте
removeObserver:
танецdealloc
, поскольку это последний момент (в жизни объекта), где вы можете сделать это чисто. Это не означает: «просто отложите удаление доdealloc
вызова, и все будет хорошо». Вместо этого удалите наблюдателя, как только объект больше не будет готов (или не требуется) для получения уведомлений . Это как раз подходящий момент. К сожалению, не зная ответов ни на один из упомянутых выше вопросов, я даже не могу предположить, когда это будет.Вы всегда можете безопасно
removeObserver:
обрабатывать объект несколько раз (и все, кроме самого первого вызова с данным наблюдателем, будут nops). Итак: подумайте о том, чтобы сделать это (снова),dealloc
чтобы быть уверенным, но прежде всего: сделайте это в подходящий момент (который определяется вашим вариантом использования).источник
dealloc
- это только последняя линия защиты от сбоя приложения из-за более позднего доступа к освобожденному объекту. Но подходящее место для отмены регистрации наблюдателя обычно находится в другом месте (и часто гораздо раньше в жизненном цикле объекта). Я не пытаюсь сказать здесь: «Эй, просто сделай это,dealloc
и все будет хорошо».viewWillDisappear
" Проблема с конкретным советом в том, что это действительно зависит от того, какой тип объекта вы регистрируете в качестве наблюдателя для какого типа события. Это может быть правильным решением для отмены регистрации наблюдателя вviewWillDisappear
(илиviewDidUnload
) наUIViewController
с, но это действительно зависит от случая использования.Примечание: это было протестировано и работает на 100%.
Swift
ПредставленныйViewController
Цель-C
В
iOS 6.0 > version
, лучше удалить наблюдателя,viewWillDisappear
посколькуviewDidUnload
метод устарел.Во многих случаях лучше,
remove observer
когда представление было удалено изnavigation stack or hierarchy
.ПредставленныйViewController
источник
viewWillAppear:
removeObserver:self
любого изUIViewController
событий жизненного цикла почти гарантированно испортит вам неделю. Дополнительная литература: subjective-objective-c.blogspot.com/2011/04/…removeObserver
вызовов,viewWillDisappear
как указано, определенно правильный путь, если контроллер представлен черезpushViewController
. Если вы вставите ихdealloc
вместо этого,dealloc
они никогда не будут вызваны - по крайней мере, по моему опыту ...Начиная с iOS 9, больше не нужно удалять наблюдателей.
https://developer.apple.com/library/mac/releasenotes/Foundation/RN-Foundation/index.html#10_11NotificationCenter
источник
Если наблюдатель добавлен к контроллеру представления , я настоятельно рекомендую добавить его
viewWillAppear
и удалитьviewWillDisappear
.источник
viewWillAppear
иviewWillDisappear
для viewControllers?dealloc
немедленного вызова. Возврат к контроллеру представления может затем вызвать несколько уведомлений, если наблюдатель добавлен в команды инициализации.источник
self
after[super dealloc]
заставляет меня нервничать ... (даже если получатель вряд ли действительно разыменует указатель каким-либо образом, ну, вы никогда не знаете, как они реализованыNSNotificationCenter
)[super dealloc]
всегда должно быть последним утверждением вашегоdealloc
метода. Он разрушает ваш объект; после его запуска у вас больше нет действительногоself
. / cc @Dirk[super dealloc]
он больше не нуженВ общем вложил в
dealloc
метод.источник
В быстром использовании deinit, потому что dealloc недоступен:
Документация Swift:
источник
* изменить: этот совет относится к iOS <= 5 (даже там вы должны добавлять
viewWillAppear
и удалятьviewWillDisappear
- однако совет применяется, если по какой-то причине вы добавили наблюдателяviewDidLoad
)Если вы добавили наблюдателя в,
viewDidLoad
вы должны удалить его как в, такdealloc
и вviewDidUnload
. В противном случае вы в конечном итоге добавите его дважды, когдаviewDidLoad
будет вызван afterviewDidUnload
(это произойдет после предупреждения памяти). Это не обязательно в iOS 6, гдеviewDidUnload
она устарела и не будет вызываться (поскольку представления больше не выгружаются автоматически).источник
На мой взгляд, следующий код не имеет смысла в ARC :
В iOS 6 также нет смысла удалять наблюдателей в
viewDidUnload
, потому что теперь он устарел.Подводя итог, я всегда делаю это внутри
viewDidDisappear
. Однако это также зависит от ваших требований, как сказал @Dirk.источник
Думаю, я нашел надежный ответ ! Мне пришлось, поскольку приведенные выше ответы неоднозначны и кажутся противоречивыми. Я просмотрел поваренные книги и руководства по программированию.
Во-первых, стиль
addObserver:
inviewWillAppear:
иremoveObserver:
inviewWillDisappear:
у меня не работает (я тестировал его), потому что я отправляю уведомление в контроллер дочернего представления для выполнения кода в контроллере родительского представления. Я бы использовал этот стиль только в том случае, если бы отправлял и слушал уведомление в том же контроллере представления.Ответ, на который я буду полагаться больше всего, я нашел в книге «Программирование для iOS: руководство Big Nerd Ranch Guide 4th». Я доверяю ребятам из BNR, потому что у них есть учебные центры iOS, и они не просто пишут очередную кулинарную книгу. Вероятно, в их интересах быть точными.
БНР, пример первый:
addObserver:
вinit:
,removeObserver:
вdealloc:
БНР, пример второй:
addObserver:
вawakeFromNib:
,removeObserver:
вdealloc:
… При удалении наблюдателя
dealloc:
они не используют[super dealloc];
Надеюсь, это поможет следующему человеку ...
Я обновляю этот пост, потому что Apple теперь почти полностью отказалась от раскадровок, поэтому вышеупомянутое может не относиться ко всем ситуациям. Важная вещь (и причина, по которой я добавил этот пост в первую очередь) - обратить внимание, если вам
viewWillDisappear:
звонят. Когда приложение вошло в фоновый режим, это было не для меня.источник
Принятый ответ небезопасен и может вызвать утечку памяти. Пожалуйста, оставьте отмену регистрации в dealloc, но также отмените регистрацию в viewWillDisappear (конечно, если вы зарегистрируетесь в viewWillAppear) .... Я ВСЕГДА ДЕЛАЛ ЭТО ТАКОЕ, И ЭТО РАБОТАЕТ ОТЛИЧНО! :)
источник
Также важно отметить, что это
viewWillDisappear
вызывается также, когда контроллер представления представляет новый UIView. Этот делегат просто указывает, что основное представление контроллера представления не отображается на дисплее.В этом случае удаление уведомления
viewWillDisappear
может быть неудобным, если мы используем уведомление, чтобы позволить UIview взаимодействовать с родительским контроллером представления.В качестве решения я обычно удаляю наблюдателя одним из этих двух методов:
По тем же причинам, когда я отправляю уведомление в первый раз, мне нужно учитывать тот факт, что каждый раз, когда над контроллером появляется представление с, тогда
viewWillAppear
метод запускается. Это, в свою очередь, создаст несколько копий одного и того же уведомления. Поскольку нет способа проверить, активно ли уведомление, я устраняю проблему, удаляя уведомление перед его добавлением:источник
SWIFT 3
Есть два случая использования уведомлений: - они нужны только тогда, когда контроллер представления находится на экране; - они нужны всегда, даже если пользователь открыл другой экран поверх текущего.
В первом случае правильное место для добавления и удаления наблюдателя:
для второго случая правильный способ:
И никогда не ставили
removeObserver
вdeinit{ ... }
- это ОШИБКА!источник
источник