.h
typedef void(^kvoBlock)(NSDictionary<NSKeyValueChangeKey,id> *dict);
@interface NSObject (YYKVO)
- (void)yyObserver:(NSObject *)object keyPath:(NSString *)keyPath block:(kvoBlock)block;
@end
.m
#import <objc/runtime.h>
typedef void(^deallocBlock)(void);
@interface YYKVOController : NSObject
/** */
@property (nonatomic, strong) NSObject *observerdObject;
/** */
@property (nonatomic, strong) NSMutableArray <deallocBlock> *blockArr;
@end
@implementation YYKVOController
- (NSMutableArray<deallocBlock> *)blockArr {
if (!_blockArr) {
_blockArr = [NSMutableArray array];
}
return _blockArr;
}
- (void)dealloc {
// 对observer remove
NSLog(@"kvoC dealloc");
[_blockArr enumerateObjectsUsingBlock:^(deallocBlock _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
obj();
}];
}
@end
@interface NSObject ()
/** dict */
@property (nonatomic, strong) NSMutableDictionary <NSString *, kvoBlock> *dict;
/** */
@property (nonatomic, strong) YYKVOController *kvoController;
@end
@implementation NSObject (YYKVO)
- (void)yyObserver:(NSObject *)object keyPath:(NSString *)keyPath block:(kvoBlock)block {
self.dict[keyPath] = block;
self.kvoController.observerdObject = object;
__unsafe_unretained typeof(self)weakSelf = self;
[self.kvoController.blockArr addObject:^{
[object removeObserver:weakSelf forKeyPath:keyPath];
}];
//监听
[object addObserver:self forKeyPath:keyPath options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:NULL];
}
// observer里调用
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
// 执行block
kvoBlock block = self.dict[keyPath];
if (block) {
block(change);
}
}
// getter setter
- (NSMutableDictionary<NSString *,kvoBlock> *)dict {
NSMutableDictionary *tempDict = objc_getAssociatedObject(self, @selector(dict));
if (!tempDict) {
tempDict = [NSMutableDictionary dictionary];
objc_setAssociatedObject(self, @selector(dict), tempDict, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
return tempDict;
}
- (YYKVOController *)kvoController {
YYKVOController *tempKvoController = objc_getAssociatedObject(self, @selector(kvoController));
if (!tempKvoController) {
tempKvoController = [[YYKVOController alloc] init];
objc_setAssociatedObject(self, @selector(kvoController), tempKvoController, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
return tempKvoController;
}
网友评论