Когда отказаться от подписки на NSNotification в UIView
Я использую следующие NSNotifications в UIView, так что представление может быть уведомлено, когда появляется UIKeyboard и настраивает его положение (кадр) на экране:
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardDidShow:) name:UIKeyboardDidShowNotification object:nil];
Два вышеупомянутых уведомления подписываются в рамках метода -init
UIView. Где лучше всего отказаться от подписки на эти уведомления после того, как представление исчезло за пределами экрана? В настоящий момент приложение сбой, всякий раз, когда UIKeyboard появляется в другом представлении, по-видимому, потому что уведомление все еще отправляется в выпущенный UIView.
Кроме того, есть ли лучшее место для подписки на уведомления, помимо метода -init
?
Спасибо за любую помощь.
Ответы
Ответ 1
-[UIView willMoveToWindow:]
и -[UIView didMoveToWindow]
вызывается даже тогда, когда представление удаляется из окна. В этом случае аргумент окна (или свойство окна в случае -didMoveToWindow
) будет равен нулю. е:.
- (void)willMoveToWindow:(UIWindow *)newWindow {
if (newWindow == nil) {
// Will be removed from window, similar to -viewDidUnload.
// Unsubscribe from any notifications here.
}
}
- (void)didMoveToWindow {
if (self.window) {
// Added to a window, similar to -viewDidLoad.
// Subscribe to notifications here.
}
}
За исключением нескольких краевых случаев, это безопасный способ сделать это. Если вам нужно больше контроля, вы можете наблюдать скрытое свойство окна, к которому принадлежит ваше представление.
Ответ 2
Я помещаю свои removeObserver
: вызовы в -dealloc
.
У нас пока не было проблем.
Ответ 3
Во-первых, вы должны учитывать, когда хотите прекратить получать уведомления:
- Когда просмотр освобожден
- Когда вид исчезает
Вы всегда должны проверить, соблюдает ли ваше наблюдение уведомления и вызывает -removeObserver:
в -dealloc
. Кроме того, если вы считаете 2, переопределите -viewWillDisappear
или -viewDidDisappear
или любую другую точку, где вы управляете иерархией представления UIViewController.
Я рекомендую поместить логику в UIViewController, потому что в терминах отношений UIView не имеет своего фрейма.
Ответ 4
Окончательный ответ (например, убедитесь, что объект перестает ссылаться на NSNotificationCenter
, когда заканчивается его жизненный цикл), чтобы делать, как @Tom предлагает и удаляет себя в качестве наблюдателя в dealloc
.
Субъективный ответ - это также хорошая практика прекратить наблюдение, когда уведомления больше не относятся к объекту. Это полностью зависит от вас, чтобы решить, основываясь на дизайне вашего приложения. Например, если у вас есть представления, которые остаются в живых, но приходят и выходят из поля зрения, вы можете начать наблюдать, когда они добавляются в подпункт, и прекращают наблюдать, когда они удаляются.
WRT, где логика уведомления должна находиться (в режиме просмотра против контроллера), что также зависит от вас, очевидно, что она может работать в обоих направлениях. Я бы принял решение на основе обстоятельств. Если обработка уведомления в представлении требует нажатия логики приложения в представление (т.е. Обработки представления как контроллера), тогда это красный флаг.
Ответ 5
Вы можете создать отдельную функцию для добавления и удаления наблюдений, а затем вы можете использовать все эти функции из экземпляра представления. Кстати, для ответа на вопрос, я бы удалил наблюдателей, прежде чем удалить представление из супервизора. Надеюсь, вы понимаете.
Ответ 6
Чтобы отказаться от подписки, вы можете использовать
- (void)removeObserver:(id)notificationObserver
или
- (void)removeObserver:(id)notificationObserver name:(NSString *)notificationName object:(id)notificationSender
Оба метода - это методы NSNotificationCenter
экземпляров.
Посмотрите Справочник класса NSNotificationCenter
Ответ 7
Как практика для клавиатурных уведомлений, я обычно использую
addObserver
в
viewWillAppear
и
removeObserver
в
viewWillDisAppear
отлично работает для меня каждый раз, и это гарантирует, что уведомление о клавиатуре не передается в представление, которое не находится на экране, что предотвращает сбой приложения из-за ложных недочетов клавиатуры.