第五、KVC对数值和结构体类型的支持
一套机制如果不支持数值和结构体型的数据,那么它的实用性就会大大折扣。幸运的是KVC中苹果对这方面的支持做的很好。KVC可以自动的将数值或结构体型的数据打包或解包成NSNumber或NSValue对象,以达到适配的目的。
举个例子,Person类有个个NSInteger类型的num属性
①修改值
我们通过KVC技术使用如下方式设置age属性的值:
[_person setValue:[NSNumber numberWithInteger:5] forKey:@"num"];
我们赋给num的是一个NSNumber对象,KVC会自动的将NSNumber对象转换成NSInteger对象,然后再调用相应的访问器方法设置age的值。
②获取值
同样,以如下方式获取age属性值:
[person valueForKey:@"num"];
这时,会以NSNumber的形式返回num的值。
第六、KVC实现原理的方法定义
在iOS中,通过KVC可以直接用字符串的名字(key)来访问类属性的机制。而不是通过调用Setter、Getter方法访问。
KVC是KVO、Core Data、CocoaBindings的技术基础,他们都是利用了OC的动态性。
NSKeyValueCodingprotocol
第七、setValue:forKey是如何访问属性值的
KVC方法的实现get、set方法及实例变量的访问,KVC setValue方法和getValue方法按顺序使用如下技术:
1. 检查是否存在set<Key>:方法
如果成员用@property,@synthsize处理,因为@synthsize告诉编译器自动生成set<Key>:格式的set方法,所以这种情况下会直接搜索到。
2. 检查名为-_<key>、-_is<key>(只针对布尔值有效)、-_set<key>:方法;
那么按_<key>,_is<Key>,<key>,is<key>的顺序搜索成员名。
3. 直接访问实例变量。实例变量可以是名为:<key>或_<key>;
4. 调用方法setValue:forUndefinedKey
第八、valueForKey是如何访问属性值的
跟上面setValue执行顺序类似,把set方法改成get方法,当所有都失效时调用方法valueForUndefinedKey。
第九、方法重写
如果我们的类既没有key或_key对应的set/get方法,也没有key或_key对应的实例变量,但要使用setValue和getValue方法,必须重写函数setValue:forUndefinedKey和valueForUndefinedKey。
在这儿我们可以利用OC的关联机制
1.什么是关联机制
OC提供了两种共享机制,一种是category,一种是associative,category只能扩展方法,associative可以扩展属性。
关联机制是基于关键字的,我们可以为任何对象增加任意多的关联,每个都使用不同的关键字即可。关联是可以保证被关联的对象在关联对象的整个生命周期都是可用的(在垃圾自动回收环境下也不会导致资源不可回收)。使用关联机制必须引入<objc/runtime.h>头文件
2.objc_setAssociatedObject创建关联
OBJC_EXPORT void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)
__OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_1);
objc_setAssociatedObject来把一个对象与另外一个对象进行关联。该函数需要四个参数:源对象,关键字,关联的对象和一个关联策略
参数说明:
object:表示源对象
key:关键词
value:表示关联的对象
policy:关联策略,关联策略表明了相关的对象是通过赋值,保留引用还是复制的方式进行关联的;还有这种关联是原子的还是非原子的。这里的关联策略和声明属性时的很类似。
policy有四个值:
OBJC_ASSOCIATION_ASSIGN = 0, /**< Specifies a weak reference to the associated object. */
OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1, /**< Specifies a strong reference to the associated object.
* The association is not made atomically. */
OBJC_ASSOCIATION_COPY_NONATOMIC = 3, /**< Specifies that the associated object is copied.
* The association is not made atomically. */
OBJC_ASSOCIATION_RETAIN = 01401, /**< Specifies a strong reference to the associated object.
* The association is made atomically. */
OBJC_ASSOCIATION_COPY = 01403 /**< Specifies that the associated object is copied.
* The association is made atomically. */