什么是KVC?通过key值,来获取对象的属性进行操作,而不是通过我们明确的存取方法获取。
一、KVC的get方法
[myObject valueForKey:@"name"];
方法去获取myObject
中name
属性或者成员变量的值。
如果myObject对象没有name属性或者成员变量,系统会出现崩溃的现象。如何解决这一问题.
1、通过重写valueForUndefinedKey
方法,来解决崩溃的问题。
- (id)valueForUndefinedKey:(NSString *)key{
return nil;
}
2、或者通过重写getName 、name或isName其中一种方法,来解决崩溃问题。KVC底层操作,valueForKey
:首先判断我们是否主动创建了属性,如果没有,就找get<Key>、<key>、is<Key>这三种方法(字符查找方式)。如果没有找到,继续按照其他类型的查找方式.访问:accessInstanceVariablesDirectly方法,如果为YES,则按照_key、_isKey、key、isKey的顺序访问成员变量.
- (NSString *)name{
NSLog(@"%s",__func__);
return @"name";
}
- (NSString *)isName{
NSLog(@"%s",__func__);
return @"isName";
}
- (NSString *)getName{
NSLog(@"%s",__func__);
return @"getName";
}
3、如果以上方法都没有,KVC会按照协议来遍历其它类型(字符串、数组、字典等)的API。
如数组类型:countOf<Key>,objectIn<Key>AtIndex
- (NSInteger)countOfName{
return 2;
}
- (id)objectInNameAtIndex:(NSInteger)index{
return @"name";
}
当我们打印出name的值
NSLog(@"%@",[myObject valueForKey:@"name"]);
结果:
name
name
二、KVC的set方法
如果myObject中没有name属性或成员变量,那么执行KVC的set方法时,运行程序时,会出现崩溃。
[myObject setValue:@"KVC" forKey:@"name"];
KVC的set方法属性名执行顺序_key、_isKey、key、isKey。
@interface MyObject ()
{
NSString * _name;
NSString * name;
NSString * isName;
}
三、如何阻止KVC来修改私有变量
+ (BOOL)accessInstanceVariablesDirectly{
return NO;
}
如果这个API返回NO,停止对key进行搜索,可以阻止外部通过KVC的方式来修改私有变量。针对KVC的set方法来说,如果该类没有_name属性,系统不会按照_key,key,isKey的顺序来对key进行赋值操作。针对KVC的get方法来说,这个API是不能阻止的。 KVC属性获取其实是对key,按规则进行一系列的搜索, 先搜索方法, 如果没找到相应的方法, 就会去看accessInstanceVariablesDirectly是否返回YES,如果返回YES继续搜索,然后搜索变量,如果返回NO,停止搜索。 总言之: 1、 先搜方法 ->accessInstanceVariablesDirectly(YES) -> 再搜变量; 2、先搜方法 ->accessInstanceVariablesDirectly(NO) -> 结束;
四、应用场景
修改私有方法。如:
[self.tf setValue:[UIColor redColor] forKeyPath:@"placeholderLabel.textColor"];