美文网首页
KVO原理解析--自定义KVO

KVO原理解析--自定义KVO

作者: rookiesss | 来源:发表于2018-12-06 10:50 被阅读0次

kvo的用法就不再赘述。

[self.name addObserver:self
                 forKeyPath:@"name"
                    options:NSKeyValueObservingOptionOld|NSKeyValueObservingOptionNew
                    context:nil];

-(void)observeValueForKeyPath:(NSString *)keyPath
                     ofObject:(id)object
                       change:(NSDictionary<NSString *,id> *)change
                      context:(void *)context{
        NSLog(@"%@", change);
}

核心思想,以观察name属性为例:
重写name属性的setter方法,当name值改变时在setter方法中调用observeValueForKeyPath方法。

先说说看我自己的思路:
1.替换name属性的setter方法。

- (void)dy_addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath 
               options:(NSKeyValueObservingOptions)options context:(nullable void *)context {

    NSString* setterMethodName = setterForGetter(keyPath);
    SEL setterSEL = NSSelectorFromString(setterMethodName);
    Method setterMethod = class_getInstanceMethod([self class], setterSEL);
    const char* setterTypes = method_getTypeEncoding(setterMethod);
  
    //替换name的setter方法自己实现
    class_replaceMethod([self class], setterSEL, (IMP)dy_setter, setterTypes);
    //将观察者存到数组作为属性,方便后面使用
    NSMutableArray *observerArr = objc_getAssociatedObject(self, (__bridge void *)@"observerArr")?: [NSMutableArray array];
    
    if (![observerArr containsObject:observer]) [observerArr insertObject:observer atIndex:0];
    objc_setAssociatedObject(self, (__bridge void *)@"observerArr", observerArr, OBJC_ASSOCIATION_RETAIN);
}

2.在name改变时通过重写name属性的setter方法调用observeValueForKeyPath方法。

static void dy_setter(id self, SEL _cmd, id newValue) {

    NSString* setterName = NSStringFromSelector(_cmd);
    NSString* key = getterForSetter(setterName);
    char *char_content = (char *)[[NSString stringWithFormat:@"_%@",key] cStringUsingEncoding:NSASCIIStringEncoding];
    Ivar ivar = class_getInstanceVariable([self class], char_content);
    //给name属性赋值
    object_setIvar(self, ivar, newValue);
    // 通知观察者, 值发生改变了
    id observerArr = objc_getAssociatedObject(self, (__bridge void *)@"observerArr");
    for (id observer in observerArr) {
        [observer observeValueForKeyPath:key ofObject:self change:@{key:newValue} context:nil];
    }
}

3.setterForGetter & getterForSetter。

#pragma mark - 从get方法获取set方法的名称 key ===>>> setKey:
static NSString  * setterForGetter(NSString *getter){
    
    if (getter.length <= 0) { return nil; }
    
    NSString *firstString = [[getter substringToIndex:1] uppercaseString];
    NSString *leaveString = [getter substringFromIndex:1];
    
    return [NSString stringWithFormat:@"set%@%@:",firstString,leaveString];
}

#pragma mark - 从set方法获取getter方法的名称 set<Key>:===> Key
static NSString * getterForSetter(NSString *setter){
    
    if (setter.length <= 0 || ![setter hasPrefix:@"set"] || ![setter hasSuffix:@":"]) { return nil;}
    
    NSRange range = NSMakeRange(3, setter.length-4);
    NSString *getter = [setter substringWithRange:range];
    NSString *firstString = [[getter substringToIndex:1] lowercaseString];
    getter = [getter stringByReplacingCharactersInRange:NSMakeRange(0, 1) withString:firstString];
    
    return getter;
}

4.移除观察者.

如果Person中重写了setName方法这样做会导致Peroson中setName无效,在苹果的实现中,先创建了一个self的子类,在子类中重写 了setName方法,这样能保证Peroson中重写的setName有效。
代码类似,代码在这里

相关文章

  • KVO基本使用

    分三部分解释KVO一.KVO基本使用二.KVO原理解析三.自定义实现KVO 一、KVO基本使用 使用KVO,能够非...

  • IOS KVO原理解析与应用

    IOS KVO原理解析与应用 一、KVO概述 KVO,即:Key-Value Observing,是Objecti...

  • KVC/ KVO

    1、kvc原理: 45页 2、自定义KVO KVO参考链接 KVO默认观察setter,使用isa-swizzli...

  • iOS-底层原理-自定义KVO

    1.自定义KVO 1.上一篇博客了解了iOS 系统KVO的底层实现原理,那么这里进行自定义KVO,更好的理解原理和...

  • KVO 解析

    KVO解析(一) —— 基本了解KVO解析(二) —— 一个简单的KVO实现KVO解析(三) —— KVO合规性K...

  • iOS - 自定义KVO

    之前我们已经了解过了KVO的底层实现原理,不过呢,在我们开始实现自定义KVO之前再来简单回顾下KVO的实现原理 1...

  • 面试题整理

    KVO原理及自定义KVO KVO原理我们注册监听的时候,会对注册者动态的创建一个子类对象,然后底层找方法的的isa...

  • Key-Value Observing(kvo)二:自定义kvo

    一、自定义kvo 在上篇文章 kvo原理分析[https://www.jianshu.com/u/a569f590...

  • iOS原理篇(一): KVO实现原理

    KVO实现原理 什么是 KVO KVO 基本使用 KVO 的本质 总结 一 、 什么是KVO KVO(Key-Va...

  • KVO原理解析--自定义KVO

    kvo的用法就不再赘述。 核心思想,以观察name属性为例:重写name属性的setter方法,当name值改变时...

网友评论

      本文标题:KVO原理解析--自定义KVO

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