通过给NSObject添加分类实现封装
使用时 对象 直接调用即可
-(void)sjyObserver:(NSObject *)object keyPath:(NSString *)keyPath block:(KVOBlock)block;
/*
* object : 观察者(一般使用 self )
* keyPath: 被观察的属性字段
* block : 观察者方法回调实现
*/
例子
Person *person = [[Person alloc] init];
person.name = @"zhangsan";
person.score = @84;
[person sjyObserver:self keyPath:@"score" block:^{
// 分数变化时实现代码
NSLog(@"分数变化了");
}];
person.score = @65; // 重新给分数赋值时会执行block 内的处理
封装代码
.h 文件
#import <Foundation/Foundation.h>
typedef void(^KVOBlock)(void);
@interface NSObject (SJYKVO)
- (void)sjyObserver:(NSObject *)object keyPath:(NSString *)keyPath block:(KVOBlock)block;
@end
.m 文件
#import "NSObject+SJYKVO.h"
#import <objc/runtime.h>
typedef void(^DeallocBlock)(void);
@interface EOCKVOController : NSObject
@property(nonatomic, strong)NSObject *observedObject;
@property(nonatomic, strong)NSMutableArray <DeallocBlock>*blockArr;
@end
@implementation EOCKVOController
-(NSMutableArray<DeallocBlock> *)blockArr {
if (!_blockArr) {
_blockArr = [NSMutableArray array];
}
return _blockArr;
}
//nextviewController -> kvoController
- (void)dealloc {
///对observedObject removeObserver
NSLog(@"kvoController dealloc");
[_blockArr enumerateObjectsUsingBlock:^(DeallocBlock _Nonnull block, NSUInteger idx, BOOL * _Nonnull stop) {
block();
}];
}
@end
@interface NSObject ()
@property(nonatomic, strong)NSMutableDictionary <NSString *, KVOBlock>*dict;
@property(nonatomic, strong)EOCKVOController *kvoController;
@end
@implementation NSObject (SJYKVO)
- (void)sjyObserver:(NSObject *)observer keyPath:(NSString *)keyPath block:(KVOBlock)block {
self.dict[keyPath] = block;
///self已经持有了kvoController
self.kvoController.observedObject = observer;
__unsafe_unretained typeof(self)weakSelf = self;
[self.kvoController.blockArr addObject:^{
[observer removeObserver:weakSelf forKeyPath:keyPath];
}];
//监听
[observer addObserver:self forKeyPath:keyPath options:NSKeyValueObservingOptionNew context:NULL];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
KVOBlock block = self.dict[keyPath];
if (block) {
block();
}
}
////getter 和 setter方法
- (NSMutableDictionary<NSString *,KVOBlock> *)dict {
NSMutableDictionary *tmpDict = objc_getAssociatedObject(self, @selector(dict));
if (!tmpDict) {
tmpDict = [NSMutableDictionary dictionary];
objc_setAssociatedObject(self, @selector(dict), tmpDict, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
return tmpDict;
}
- (EOCKVOController *)kvoController {
EOCKVOController *tmpKvoController = objc_getAssociatedObject(self, @selector(kvoController));
if (!tmpKvoController) {
tmpKvoController = [[EOCKVOController alloc] init];
objc_setAssociatedObject(self, @selector(kvoController), tmpKvoController, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
return tmpKvoController;
}
@end