问题:为什么 NotificationCenter 要 remo
2020-05-11 本文已影响0人
姜小舟
-
首先要先了解一下__unsafe_unretain
__unsafe_unretain和__weak都能避免retain cycle,但是他们也有一些细微的不同。对于__weak,当释放指针指向的对象时,该对象的指针将转换为nil,这是比较安全的行为。而__unsafe_unretain,正如其名称隐藏的含义,尽管释放指针指向的对象时,该指针将继续指向原来的内存。这将会导致应用crash,所以是unsafe
-
通知中心对响应者observer是使用unsafe_unretained修饰。
当响应者释放会出现野指针,如果向野指针发送消息会造成崩溃。在 iOS9 系统之后,[NSNotificationCenter defaultCenter]会在响应者observer调用-dealloc方法的时候执行-removeObserver:方法
-
如何证明响应者dealloc时候调用了removeObserver?
写个NSNotificationCenter的 分类 ,拦截removeObserver ,发现当响应者dealloc时候确实调用removeObserver
+ (void)load { Methodorigin =class_getInstanceMethod([selfclass],@selector(removeObserver:)); Methodcurrent =class_getInstanceMethod([selfclass],@selector(_removeObserver:)); method_exchangeImplementations(origin, current); } - (void)_removeObserver:(id)observer { NSLog(@"调用移除通知方法: %@", observer); // [self _removeObserver:observer]; }
实现自动remove的两种方式:
- 通过自释放机制,通过动态属性将remove转移给第三者,解除耦合,达到自动实现remove。
- 我们一般在dealloc方法里面做remove observer的操作。那么就hook dealloc方法就好了
// 替换dealloc方法,自动注销observer+ (void)load { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ Method originalDealloc = class_getInstanceMethod(self, NSSelectorFromString(@"dealloc")); Method newDealloc = class_getInstanceMethod(self, @selector(autoRemoveObserverDealloc)); method_exchangeImplementations(originalDealloc, newDealloc); }); } - (void)autoRemoveObserverDealloc { if (objc_getAssociatedObject(self, &KTKvoObserversKey) || objc_getAssociatedObject(self, &KTNotificationObserversKey)) { [self removeAllObserverBlocks]; [self removeAllNotificationBlocks]; } // 下面这句相当于直接调用dealloc [self autoRemoveObserverDealloc]; }