仿照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