ios-KVC深入

来源:互联网 发布:数据防泄漏国内厂家 编辑:程序博客网 时间:2024/05/19 23:02

KVC全称Key Value Coding也就是键值编码,当在同时实现setter和getter时,类中的@property不会自动生成带下滑线的成员变量,而我们如果去定义了一个带下划线的成员变量NSString * _bookName; 然后我们在外面使用的时候[stu setValue:@"kkk" forKey:@"_bookName"]; 也是已经给bookName赋值了,,因为Xcode会默认将self.bookName与自定义成员变量_bookName关联。

当然如果我们直接使用@synthesize bookName = _bookName; 然后在外面用KVC对_bookName赋值的话也是可以赋值的,因为写了这句话之后其实就相当于是把bookName和_bookName给联系起来了。

当然如果我们采取@synthesize bookName = _obj; 一样在外面通过KVC给_obj设置值一样会关联到bookName。

一般来说在KVC中我们使用了ValueForKey想去寻找key对应的值的话,会先去找相关的方法,再去找相关的变量。

如果说我们相关的方法找不到的时候,才会去找相关的变量,这点可以在下面中进行证明,当我们定义了下面这样的属性

@property (nonatomic ,strong)NSString *name;//以及我们写了下面这个方法-(NSString *)getName{    _name=@"qqq";    return @"kkdjskja";}//然后根据key是name去获取值,获取到的是kkdjskja,而我们打印student的name是qqq NSString * str = [student valueForKey:@"name"];

还有需要了解的是,如果我们的属性是有用readonly修饰的,并且实现了下面的这个方法,那么我们是无法用KVC给这个属性赋值的,这个方法默认返回 YES,也就是说在不存在满足条件的方法时,允许直接访问属性对应的实例变量,如果我们返回NO就表示不允许访问。但如果去掉readonly还是可以赋值的。

以及我们在使用[student setValue:@"qweqwe" forKey:@"name"];赋值的时候回优先去找setName的方法,如果找不到方法然后再去找成员变量,然后再去赋值。当然这个前提是下面的这个方法要返回YES。

+(BOOL)accessInstanceVariablesDirectly{    return NO;}


还有就是我们在类扩展中定义的变量也是无法通过KVC进行赋值的,如果我们上面的这个方法也返回了NO。

@interface Student(){   NSString * name;}

当然也无法通过valueForKey去访问它的值。去寻找相应的Value是优先去找get<Key>然后再去找<key>方法。

还有就是当我们有一个变量是基本数据类型的时候,使用valueForKey会帮我们转换成NSNumber类型。

如果我们定义的是成员变量NSString * _name;则我们在使用setValue ForKey赋值的时候可能会调用两个方法,如果两个方法都实现了就只会调用优先级高的也就是setName方法

优先级低的是setIsName方法。但如果我们定义的是属性name,如果去使用KVC赋值的时候以及只实现了setIsName方法也不会去调用setIsName方法。

-(void)setName:(NSString *)name{    NSLog(@"dadaokiji");}-(void)setIsName:(NSString *)name{    NSLog(@"12131");}

我们如果在一个类中有这些成员变量的话,那么赋值的过程是有顺序的,如下所示,比如说我们通过valueForKey:@"name"去获取值,获取到的顺序如下所示,也就是说如果不存在满足条件的方法,以及+ (BOOL)accessInstanceVariablesDirectly 返回 YES,那么就会以 _<key> , _is<Key> , <key> , is<Key> 的顺序查找是否存在对应的key。

    NSString * isName;//4    NSString * _isName;//2    NSString * name;//3    NSString * _name;//1
还有一个就是我们如果再类的内部有一个属性是大写开头的比如说Nook,我们在外部用KVC把key设置成nook也是可以赋值的。