美文网首页
问题:为什么 NotificationCenter 要 remo

问题:为什么 NotificationCenter 要 remo

作者: 姜小舟 | 来源:发表于2020-05-11 18:22 被阅读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];
    }
    

相关文章

网友评论

      本文标题:问题:为什么 NotificationCenter 要 remo

      本文链接:https://www.haomeiwen.com/subject/cbcpnhtx.html