setValue:forKey:方法实现原理

1、首先去接收者(调用方法的那个对象)的类中查找与key相匹配的访问器方法(-set)

  • 如果找到了一个方法,就检查它参数的类型
  • 如果它的参数类型不是一个对象指针类型,但是只为nil,就会执行setNilValueForKey:方法,setNilValueForKey:方法的默认实现,是产生一个NSInvalidArgumentException的异常,但是你可以重写这个方法
  • 如果方法参数的类是一个对象指针类型,就会简单的执行这个方法,传入对应的参数
  • 如果方法的参数类型是NSNumber或NSValue的对应的基本类型,先把它转换为基本数据类,再执行方法,传入转换后的数据

2、如果没有对应的访问器方法(setter方法)接受者的类的+accessInstanceVariablesDirectly方法返回YES,那么就查找这个接受者的与key相匹配的实例变量(匹配模式为_,_is,,is):

  • 比如:key为age,只要属性存在_age,_isAge,age,isAge中的其中一个就认为匹配上了
    • 如果找到这样的一个实例变量,并且的类型是一个对象指针类型,首先released对象上的旧值,然后把传入的新值retain后的传入的值赋值该成员变量
    • 如果方法的参数类型是NSNumber或NSValue的对应的基本类型,先把它转换为基本数据类,再执行方法,传入转换后的数据.**

3、如果访问器方法和实例变量都没有找到,执行setValue:forUndefinedKey:方法,该方法的默认实现是产生一个 NSUndefinedKeyException 类型的异常,但是我们可以重写setValue:forUndefinedKey:方法

以name属性为例

  • 首先先去类的方法列表去寻找有没有setName:,如果有,就直接调用[person setName:value]
  • 找有没有带下划线的成员变量_name,如果有 _name = value;
  • 找有没有成员变量name,如果有 name = value;
  • 如果都没有找到,执行setValue:forUndefinedKey:方法,该方法的默认实现是产生一个NSUndefinedKeyException类型的异常,但是我们可以重写setValue:forUndefinedKey:方法。

ValueForKey同setValue:forKey:

  • 首先查找有没有对应get方法
  • 找有没有带下划线的成员变量
  • 找有没有不带下划线的成员变量
  • 都没找到就调用undefinedKey.

你可能感兴趣的:(setValue:forKey:方法实现原理)