美文网首页
iOS 开发 - KVO的封装

iOS 开发 - KVO的封装

作者: cgfloat | 来源:发表于2019-03-19 17:55 被阅读0次

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

    相关文章

      网友评论

          本文标题:iOS 开发 - KVO的封装

          本文链接:https://www.haomeiwen.com/subject/xmpnmqtx.html