何时取消订阅UIView中的NSNotification
我在UIView中使用下面的NSNotifications,以便UIKeyboard出现时可以通知视图,并在屏幕上调整它的位置(框架):
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardDidShow:) name:UIKeyboardDidShowNotification object:nil];
上面的两个通知正在UIView的-init
方法中订阅。 一旦视图从屏幕上消失,最好的地方在哪里取消订阅这些通知? 目前,当UIKeyboard出现在另一个视图中时,应用程序崩溃,大概是因为通知仍然被发送到当时发布的UIView。
另外,除了-init
方法之外,还有更好的地方可以订阅通知吗?
感谢您的帮助。
即使从窗口中删除视图,也会调用-[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. } }
除了几个边缘情况,这是一个安全的方法来做到这一点。 如果您需要更多的控制权,您可以观察视图所属窗口的隐藏属性。
我把我的removeObserver
:调用放在-dealloc
。
到目前为止没有任何问题。
首先,您应该考虑何时停止接收通知:
- 当查看被释放
- 当视图消失时
您应该始终检查您的视图是否遵守通知,并调用-removeObserver:
in -dealloc
。 另外,如果你考虑2,覆盖-viewWillDisappear
或-viewDidDisappear
或者你操纵视图的UIViewController的视图层次的任何其他点。
我build议你将逻辑放入UIViewController,因为在关系方面UIView不拥有它的框架。
明确的答案(例如,确保NSNotificationCenter
在其生命周期结束时不再引用某个对象)将按照@Tom的build议并在dealloc
以观察者身份移除自己。
主观的答案是,当通知不再与对象相关时,停止观察也是一种好的做法。 这完全取决于您根据您的应用程序的devise来决定。 例如,如果您的视图保持活跃状态,但进入和离开视图,则可能会决定在添加到子视图时开始观察,并在删除视图时停止观察。
WRT的通知逻辑应该驻留(在视图vs控制器),这也取决于你,显然它可以同时工作。 我会根据情况做出决定。 如果在视图中处理通知需要将应用程序逻辑推入视图(即将控件视为控制器),那么这是一个红旗。
你可以创build一个单独的函数来添加和删除观察,然后你可以从视图的实例中的所有这些function。 顺便问你的问题的答案,我会删除观察员,然后从超视图中删除视图本身。 我希望你明白。
要取消订阅,您可以使用
- (void)removeObserver:(id)notificationObserver
要么
- (void)removeObserver:(id)notificationObserver name:(NSString *)notificationName object:(id)notificationSender
两种方法都是NSNotificationCenter
的实例方法。
看看NSNotificationCenter类参考
作为键盘通知的做法,我通常使用
的addObserver
在
viewWillAppear中
和
removeObserver
在
viewWillDisAppear
每次都对我很好,它确保没有键盘通知被传递到不在屏幕上的视图,从而防止由于错误的键盘通知而使应用程序崩溃。