iOS笔记系列目录

一 Getter

- (nullable id)valueForKey:(NSString *)key;                          //直接通过Key来取值
- (nullable id)valueForKeyPath:(NSString *)keyPath;                  //通过KeyPath来取值

image.png

  • 1.通过getter方法搜索实例,按照get<Key>, <key>, is<Key>, _<key>的顺序查找getter`方法。如果发现符合的方法,就调用对应的方法并拿着结果跳转到第五步。否则,就继续到下一步。
  • 2.如果没有找到简单的getter方法,则搜索其匹配模式的方法countOf<Key>objectIn<Key>AtIndex:<key>AtIndexes:
    如果找到其中的第一个和其他两个中的一个,则就会返回一个可以响应NSArray所有方法的代理集合(它是NSKeyValueArray,是NSArray的子类)。或者说给这个代理集合发送属于NSArray的方法,就会以countOf<Key>,objectIn<Key>AtIndex<Key>AtIndexes这几个方法组合的形式调用。否则,继续到第三步。
    代理对象随后将NSArray接收到的countOf<Key>objectIn<Key>AtIndex:<key>AtIndexes:的消息给符合KVC规则的调用方。
    当代理对象和KVC调用方通过上面方法一起工作时,就会允许其行为类似于NSArray一样。
  • 3.如果没有找到NSArray简单存取方法,或者NSArray存取方法组。那么会同时查找countOf<Key>enumeratorOf<Key>memberOf<Key>:命名的方法。
    如果找到三个方法,则创建一个集合代理对象,该对象响应所有NSSet方法并返回。否则,继续执行第四步。
    给这个代理对象发NSSet的消息,就会以countOf<Key>enumeratorOf<Key>,memberOf<Key>组合的形式调用。
  • 4.如果没有发现简单getter方法,或集合存取方法组,以及接收类方法accessInstanceVariablesDirectly是返回YES的。搜索一个名为_<key>_is<Key><key>is<Key>的实例,根据他们的顺序。
    如果发现对应的实例,则立刻获得实例可用的值并跳转到第五步,如果重写了类方法+ (BOOL)accessInstanceVariablesDirectly返回NO的话,那么会直接调用valueForUndefinedKey:
  • 5.如果取回的是一个对象指针,则直接返回这个结果。
    如果取回的是一个基础数据类型,但是这个基础数据类型是被NSNumber支持的,则存储为NSNumber并返回。
    如果取回的是一个不支持NSNumber的基础数据类型,则通过NSValue进行存储并返回。
  • 6.如果所有情况都失败,则调用valueForUndefinedKey:方法并抛出异常,这是默认行为。但是子类可以重写此方法。

二 Setter

- (void)setValue:(nullable id)value forKey:(NSString *)key;          //通过Key来设值
- (void)setValue:(nullable id)value forKeyPath:(NSString *)keyPath;  //通过KeyPath来设值

image.png

  • 1.查找set<Key>:_set<Key>命名的setter,按照这个顺序,如果找到的话,代码通过setter方法完成设置。
  • 2.如果没有找到setter方法,KVC机制会检查+ (BOOL)accessInstanceVariablesDirectly的返回值,如果accessInstanceVariablesDirectly类属性返回YES,则查找一个命名规则为_<key>_is<Key><key>is<Key>的实例变量。根据这个顺序,如果发现则将value赋值给实例变量,如果返回值为NO,KVC会执行setValue:forUndefinedKey:方法。
  • 3.如果没有发现setter或实例变量,则调用setValue:forUndefinedKey:方法,并默认提出一个异常,但是一个NSObject的子类可以提出合适的行为。

Adrenine
9 声望3 粉丝

最怕一生碌碌无为却道平凡难能可贵!