Mic*_*iZH 29 objective-c nsnotificationcenter ios
我在大多数视图控制器中注册了三个观察者.有些人有更多,有些人更少,但我想在父类中包含部分注册和注销过程.即使没有观察者,调用取消注册有什么问题吗?是否要求所有三位观察员取消注册?
- (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];
}
Run Code Online (Sandbox Code Playgroud)
rob*_*off 59
是的,这将删除观察者所在的所有注册self.它在NSNotificationCenter类参考中有记录:
以下示例说明了如何取消注册
someObserver之前已注册的所有通知:Run Code Online (Sandbox Code Playgroud)[[NSNotificationCenter defaultCenter] removeObserver:someObserver];
请注意,理论上(但据我所知,在iOS 7.0的实践中),UIViewController可能有自己的注册,它不想删除viewWillDisappear:.它不太可能在公共API中使用注册任何通知addObserver:selector:name:object:,因为这将阻止您在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];
}
Run Code Online (Sandbox Code Playgroud)
另一种方法是使用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];
}
Run Code Online (Sandbox Code Playgroud)
由于返回的每个观察者addObserverForName:object:queue:usingBlock:都是一个只有一个注册的新对象,因此每个调用removeObserver:都保证只删除该观察者的一个注册.
从iOS 9和macOS 10.11开始,NSNotificationCenter如果取消分配观察者,则自动取消注册观察者.如果您的部署目标是iOS 9或更高版本或macOS 10.11或更高版本,则不再需要在您的dealloc方法(或deinitSwift)中手动取消注册.
对于你的第一个问题,即使没有观察者也可以取消注册.但是对于你移除观察者的方式,[[NSNotificationCenter defaultCenter] removeObserver:someObserver];甚至会删除超级观察者,这是非常不推荐的(除了因为对象被卸载而在dealloc中),但viewWillDisappear你应该通过使用逐个删除观察者[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil];