-
方法
- (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 -
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; //和上一个方法一样,但这个方法是设值。 -
键值校验,在这个方法中写入value校验的逻辑,符合逻辑可以set成功,不符合逻辑,set不成功
-
- (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; } -
次方法需要配合下面这个方法,手动调用
- (BOOL)validate<Key>:error: -
实例
@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; } -
kvc的应用:用kvc来访问和修饰私有变量;model和字典的转换,kvc配合runtime
-
kvo实现的原理。生成一个临时的子类,把isa指针指向新的子类,并且重写子类的setter方法
[self willChangeValueForeKey:@"age"]; //原来的setter方法 [self setAge:]; [self didChangeValueForKye:@"age"]; -
同样可以手动出发kvo
-
kvo还会重新class方法,为了隐藏新生成的临时的子类名字