首页 > 代码库 > KVC实现原理

KVC实现原理

KVC实现原理

在iOS中,通过KVC可以直接用字符串的名字(key)来访问类属性的机制。而不是通过调用Setter、Getter方法访问。

KVC是KVO、Core Data、CocoaBindings的技术基础,他们都是利用了OC的动态性。

关于KVC的使用方法,在博客http://blog.csdn.net/richard_rufeng/article/details/15409123 有详细的介绍,在这儿我们重点介绍KVC的实现原理。

第一、方法定义

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. */


     3. objc_getAssociatedObject获取关联对象

OBJC_EXPORT id objc_getAssociatedObject(id object, const void *key)

    __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_1);

4.objc_removeAssociatedObjects删除该对象的所有关联,通常情况下不建议使用这个函数,因为他会断开所有关联。只有在需要把对象恢复到“原始状态”的时候才会使用这个函数。

OBJC_EXPORT void objc_removeAssociatedObjects(id object)

    __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_1);

5. objc_setAssociatedObject with nil 来断开指定key得关联

6. 重写方法的实现

<span style="font-size:18px;">- (void)setValue:(id)value forUndefinedKey:(NSString *)key {
    objc_setAssociatedObject(self, key, value, OBJC_ASSOCIATION_RETAIN);
}

- (id)valueForUndefinedKey:(NSString *)key {
    id target = objc_getAssociatedObject(self, key;
    if ([target isKindOfClass:[NSNull class]])
        return nil;
    return target;
}</span>





KVC实现原理