iOS 开发 - KVO的封装

.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;
}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容