正文
LXObj *obj = [[LXObj alloc] init];
[obj setValue:@"i am a ivar" forKey:@"ivar"];
NSLog(@"%@", [obj valueForKey:@"ivar"]);
运行结果如下:
那么我们再来看一下KVC访问下的所谓obj-C私有变量,首先在类中添加私有变量:
@interface LXObj : NSObject {
@private NSString *privateIvar;
}
或者在类扩展中声明变量:
@interface LXObj ()
@property (nonatomic, copy) NSString *privateIvar;
@end
为了解释的更明白,让所有人(包括一些初学obj-C的小伙伴)看懂,先用普通的方式访问:
都编译不过去,静态分析器就帮我们找到了错误,那么我们换KVC方式访问:
LXObj *obj = [[LXObj alloc] init];
[obj setValue:@"i am a private ivar" forKey:@"privateIvar"];
NSLog(@"%@", [obj valueForKey:@"privateIvar"]);
然后运行,发现可以正常运行:
看到这,你会得出或者印证你以前学习obj-C时书上提到的:obj-C实际上并不存在真正的私有变量,因为只要知道变量名称就可以访问且操作这个变量。
你不要萌萌的瞪着眼睛问我:我们为啥还要遵守规则把变量写在.m内的类扩展中呢?
因为当你的app提交到appstore中被人下载得到下载包后,别人反编译分分钟就能看到你的项目头文件,类名和方法。
2.使用KVC会自动开/封箱
如果你想设置一个标准量,在调用- (void)setValue:(nullable id)value forKey:(NSString *)key方法之前需要将它们封箱:
先给LXObj类添加一个floatNum属性:
@property (nonatomic, assign) float floatNum;
然后执行下面代码:
LXObj *obj = [[LXObj alloc] init];
[obj setValue:[NSNumber numberWithFloat:0.1] forKey:@"floatNum"];
这时,- (void)setValue:(nullable id)value forKey:(NSString *)key方法会先开箱取出该值,再调用- (void)setFloatNum:方法或者直接更改floatNum实例变量,反之:
LXObj *obj = [[LXObj alloc] init];NSLog(@"%@", [obj valueForKey:@"floatNum"]);
代码中[obj valueForKey:@"floatNum"]方法会先取出floatNum属性的值并封箱打印出来。
3.键路径
当类中包含其他类类型的属性时,可以直接使用键路径来操作这个属性内部的变量。
先定义一个LXSubObj类,其中包含一个属性subIvar:
@interface LXSubObj : NSObject@property (nonatomic, copy) NSString *subIvar;@end