iOS kvc/kvo复习

34 阅读2分钟
  1. 方法 

    - (nullable id)valueForkey:(NSString *)key;
    - (void)setValue:(nullable id)value forKey:(NSString *)key;
    - (nullable)valueForkeyPath:(NSString *)keyPath;
    - (void)setValue:(nullable id)value forKeyPath:(NSString *)keypath
    
  2. KSKeyValueCoding类别中其他的一些方法:

    +(BOOL)accessInstanceVarialbeDirectly;
    ////默认返回YES,表示如果没有找到Set<Key>方法的话,会按照_key,_iskey,key,iskey的顺序搜索成员,设置成NO就不这样搜索
    
    - (nullable id)valueForUndefinedKey:(NSString *)key;
    //如果Key不存在,且没有KVC无法搜索到任何和Key有关的字段或者属性,则会调用这个方法,默认是抛出异常
    - (void)setValue:(nullable id)value forUndefinedKey:(NSString *)key;
    //和上一个方法一样,但这个方法是设值。
    
    
  3. 键值校验,在这个方法中写入value校验的逻辑,符合逻辑可以set成功,不符合逻辑,set不成功

  4.  - (BOOL)validateValue:(inout id  _Nullable __autoreleasing *)ioValue forKey:(NSString *)inKey error:(out NSError * _Nullable __autoreleasing *)outError {
         NSNumber *age = *ioValue;
         if (age.integerValue == 10) {
             return NO;
         }
         
         return YES;
     }
    
  5. 次方法需要配合下面这个方法,手动调用

    - (BOOL)validate<Key>:error:
    
  6. 实例

    @interface Test: NSObject {
        NSUInteger _age;
    }
    
    @end
    
    @implementation Test
    
    - (BOOL)validateValue:(inout id  _Nullable __autoreleasing *)ioValue forKey:(NSString *)inKey error:(out NSError * _Nullable __autoreleasing *)outError {
        NSNumber *age = *ioValue;
        if (age.integerValue == 10) {
            return NO;
        }
        
        return YES;
    }
    
    @end
    
    int main(int argc, const char * argv[]) {
        @autoreleasepool {
            // insert code here...
            
            //Test生成对象
            Test *test = [[Test alloc] init];
            //通过KVC设值test的age
            NSNumber *age = @10;
            NSError* error;
            NSString *key = @"age";
            BOOL isValid = [test validateValue:&age forKey:key error:&error];
            if (isValid) {
                NSLog(@"键值匹配");
                [test setValue:age forKey:key];
            }
            else {
                NSLog(@"键值不匹配");
            }
            //通过KVC取值age打印
            NSLog(@"test的年龄是%@", [test valueForKey:@"age"]);
            
        }
        return 0;
    }
    
  7. kvc的应用:用kvc来访问和修饰私有变量;model和字典的转换,kvc配合runtime

  8. kvo实现的原理。生成一个临时的子类,把isa指针指向新的子类,并且重写子类的setter方法

    [self willChangeValueForeKey:@"age"];
    //原来的setter方法
    [self setAge:];
    [self didChangeValueForKye:@"age"];
    
  9. 同样可以手动出发kvo

  10. kvo还会重新class方法,为了隐藏新生成的临时的子类名字