自动移除observer的KVO和Notification

仿照https://github.com/X-Team-X/SimpleKVO写的,添加KVO和Notification观察者非常容易,自动移除observer。不需要手动在dealloc中添加如下代码:

- (void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationWillEnterForegroundNotification object:nil];
    [self.tableView removeObserver:self forKeyPath:NSStringFromSelector(@selector(contentOffset))];
}

用block的方式传回回调,而且也不用担心没有移除observer导致的crash了,用法如下:

- (void)viewDidLoad {
    [super viewDidLoad];
    
    [self.tableView addObserverForKeyPath:NSStringFromSelector(@selector(contentOffset)) block:^(__weak id obj, id oldValue, id newValue) {
        NSLog(@"old value:%@ new value:%@", NSStringFromCGPoint([oldValue CGPointValue]), NSStringFromCGPoint([newValue CGPointValue]));
    }];
    [self addNotificationForName:UIApplicationWillEnterForegroundNotification block:^(NSNotification *notification) {
        NSLog(@"will enter forground");
    }];
}

自动移除observer的原理很简单,因为我们一般在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];
}

完整项目在这里SimpleKVONotification

你可能感兴趣的:(自动移除observer的KVO和Notification)