NotificationCenter: BAD_ACCESS при отправке уведомления

У меня есть приложение с 3 контроллерами просмотра, которые помещаются в стек навигационного контроллера.

(A) -> (B) -> (C)

(A) регистрируется для получения уведомлений в viewWillAppear:

NotificationCenter.default.addObserver(self, selector: #selector(reload), name: NSNotification.Name(rawValue: "DATA_CHANGED"), object: nil)

и (A) отменяет регистрацию в viewWillDisappear:

NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: "DATA_CHANGED"), object: nil)

Кроме того, (A) отменяет регистрацию в deinit(), но никогда не вызывается.

Теперь (B) помещается в стек и регистрируется/отменяется для того же события, что и (A).

Теперь (C) помещается в стек, который запускает вычисление и возвращается к (B). Некоторое время спустя, когда представлено (B), вычисление завершено, и запускается уведомление:

NotificationCenter.default.post(name: NSNotification.Name(rawValue: "DATA_CHANGED"), object: nil)

Но это приводит к

Тема 1: EXC_BAD_ACCESS

Я уверен, что проблема заключается в уведомлении, потому что я неправильно написал имя уведомления, и тогда сбоя не произошло. Кроме того, (A) и (B) все еще не освобождены, так как живут в стеке. Я не смог найти зомби в Profiler.

Есть идеи, в чем может быть проблема?

Я использую XCode 9beta6 и Swift 4.


person netshark1000    schedule 22.08.2017    source источник
comment
Пожалуйста, отредактируйте свой вопрос, чтобы показать трассировку стека.   -  person Paulw11    schedule 22.08.2017
comment
Трассировки стека нет. Я получаю только EXC_BAD_ACCESS в виде красной строки.   -  person netshark1000    schedule 22.08.2017
comment
Установите точку останова исключения, чтобы получить затронутую строку, фактическую причину исключения и трассировку стека. Скорее всего подпись селектора неверна.   -  person vadian    schedule 22.08.2017
comment
Да - имя селектора было неправильным... Если вы напишете ответ, чтобы проверить имя селектора, я могу его принять. Спасибо   -  person netshark1000    schedule 22.08.2017


Ответы (2)


Поэтому я потратил около 4 часов на исправление этого в своем собственном коде. Вот какая у меня была проблема:

Функция, которую я указал в своем селекторе, имела необязательный параметр со значением по умолчанию nil. Мой селектор тогда выглядел точно так же, как и ваш - без списка параметров. Однако, когда я запускал уведомление, я получал EXC_BAD_ACCESS.

Я пытался вызвать родительскую функцию с помощью моего селектора по отношению к дочернему классу, для которого я регистрировал уведомление. Мне пришлось создать вспомогательную функцию для дочернего класса и вызвать родительскую функцию.

Если у вас есть необязательный параметр в перезагрузке и/или перезагрузка является функцией в родительском классе, попробуйте создать вспомогательную функцию, которая вызывает перезагрузку, и сделайте так, чтобы ваш селектор указывал на нее.

person Michael Curtis    schedule 24.08.2017
comment
Спасибо за совет. У меня был почти аналогичный случай. У меня был дополнительный параметр в функции, которую я указал в селекторе. - person Roman Romanenko; 10.07.2019
comment
спасибо, я был в том же месте. очень странная авария и никаких намеков ???? - person Radu Ursache; 08.10.2020

Вы регистрируете уведомление с именем "BACKEND_DATA_CHANGED" и отменяете регистрацию "DATA_CHANGED". Это разные уведомления.

person Arman Galstyan    schedule 22.08.2017
comment
извините - я упростил пример и допустил там ошибку. Теперь это правильно - person netshark1000; 22.08.2017
comment
Вы получаете ту же ошибку, даже если имена верны? - person Arman Galstyan; 22.08.2017