[英]iOS Remove observer from notification: Can I call this once for all observers? And even if there are none?
我在大多數視圖控制器中注冊了三個觀察者。 有些人有更多,有些人更少,但我想在父類中包含部分注冊和注銷過程。 即使沒有觀察者,調用取消注冊有什么問題嗎? 是否要求所有三位觀察員取消注冊?
- (void)registerForKeyboardNotifications
{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWasShown:)
name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillBeHidden:)
name:UIKeyboardWillHideNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(applicationWillEnterBackground:)
name:UIApplicationWillResignActiveNotification
object:nil];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
//Has to be unregistered always, otherwise nav controllers down the line will call this method
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
是的,這將刪除觀察者self
所有注冊。 它在NSNotificationCenter類參考中有記錄 :
以下示例說明了如何
someObserver
注冊的所有通知取消注冊someObserver
:[[NSNotificationCenter defaultCenter] removeObserver:someObserver];
請注意,理論上(但據我所知,在iOS 7.0的實踐中), UIViewController
可能有自己的注冊,它不希望在viewWillDisappear:
刪除viewWillDisappear:
。 使用addObserver:selector:name:object:
注冊公共API中的任何通知是不太可能的,因為這會阻止您在UIViewController
子類中注冊它們,但它當然可以注冊非公開通知或現在注冊未來的版本。
取消注冊的一種安全方法是發送removeObserver:name:object:
每次注冊一次:
- (void)deregisterForKeyboardNotifications {
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
[center removeObserver:self name:UIKeyboardWillShowNotification object:nil];
[center removeObserver:self name:UIKeyboardWillHideNotification object:nil];
[center removeObserver:self name:UIApplicationWillResignActiveNotification object:nil];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[self deregisterForKeyboardNotifications];
}
- (void)dealloc {
[self deregisterForKeyboardNotifications];
}
另一種方法是使用addObserverForName:object:queue:usingBlock:
來注冊(而不是addObserver:selector:name:object:
。 這將為每個注冊返回一個新的觀察者對象引用。 您必須將它們保存起來(如果您不想創建單個實例變量,可能在NSArray
實例變量中)。 然后,您將每個傳遞給removeObserver:
取消注冊其通知。 例:
@implementation MyViewController {
NSMutableArray *observers;
}
- (void)registerForKeyboardNotifications {
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
NSOperationQueue *queue = [NSOperationQueue mainQueue];
__weak MyViewController *me = self;
observers = [NSMutableArray array];
[observers addObject:[center addObserverForName:UIKeyboardWillShowNotification
object:nil queue:queue usingBlock:^(NSNotification *note) {
[me keyboardWillShow:note];
}]];
[observers addObject:[center addObserverForName:UIKeyboardWillHideNotification
object:nil queue:queue usingBlock:^(NSNotification *note) {
[me keyboardWillHide:note];
}]];
[observers addObject:[center addObserverForName:UIApplicationWillResignActiveNotification
object:nil queue:queue usingBlock:^(NSNotification *note) {
[me applicationWillResignActive:note];
}]];
}
- (void)deregisterForKeyboardNotifications {
for (id observer in observers) {
[[NSNotificationCenter defaultCenter] removeObserver:observer];
}
observers = nil;
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[self deregisterForKeyboardNotifications];
}
- (void)dealloc {
[self deregisterForKeyboardNotifications];
}
由於addObserverForName:object:queue:usingBlock:
返回的每個觀察者addObserverForName:object:queue:usingBlock:
是一個只有一個注冊的新對象,因此每次調用removeObserver:
都保證只刪除該觀察者的一個注冊。
從iOS 9和macOS 10.11開始,如果取消分配觀察者, NSNotificationCenter
自動取消注冊觀察者。 它不再需要手動注銷自己在您dealloc
方法(或deinit
斯威夫特)如果您的部署目標是iOS的9或更高版本或者MacOS 10.11或更高版本。
對於你的第一個問題,即使沒有觀察者也可以取消注冊。 但是對於你移除觀察者的方式, [[NSNotificationCenter defaultCenter] removeObserver:someObserver];
甚至會刪除非常推薦的超類觀察者(因為對象被卸載除了dealloc),但是在viewWillDisappear
你應該使用[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil];
刪除觀察者[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil];
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.