我们知道KVC时,当valueForKey:和
setValue:forKey:被调用时,对应key的accessor method会被调用,这里我们介绍Key-Value Coding Accessor,通过此文,我们应该对KVC和Accessor的关系会更清楚。
之前我们也介绍过类的ivars与owning object共有4种关系:attribute, to-one relationship , ordered to-many relationship, unordered to-many relationship, 介绍Accessor也要根据这4中关系介绍。
Basic Accessor Method ( apply for attribute, to-one relationship, ordered to-many relationship, unordered to-many relationship)
4种关系都有基本的通用的Accessor Method。其getter方法的模式是-<key>或者-is<Key>(只有对Boolean属性有效),其setter方法的模式是set<Key>:,这种方式在用到to-many relationship时,只用于创建或者访问整个Collection,但不能访问Collection中的某个对象。下面是例子:
collection accessor methods (for ordered to-many relationship)
对于这种关系,还有其他的Accessor方法用于access 其collection内容对象。best practice是使用collection accessor methods或者由mutableArrayValueForKey: 或者 mutableSetValueForKey: 返回的mutable collection proxy。
Indexed Accessor Methods定义了一种在ordered collection中进行counting, retrieving, adding, and replacing的机制。通常这种关系使用NSArray或者NSMutableArray实现,但其实任何对象都可以实现这些方法,并像操作数组一样操纵数据。
- -countOf<Key> 必须实现,对应于NSArray的基本方法count:
- -objectIn<Key>AtIndex: or -<key>AtIndexes:. 两个必须实现一个,对应于 NSArray 的方法 objectAtIndex: 和 objectsAtIndexes:
- -get<Key>:range: 不是必须实现的,但实现后可以提高性能,其对应于 NSArray 方法 getObjects:range:
Mutable Indexed Accessors
这部分方法可以使得我们的程序可以以一种简单高效的方式通过mutableArrayValueForKey:返回的NSArray proxy对象访问indexed collections。而且实现这些方法,就可以使得此class 符合Key-Value Coding规范的要求。为了与Key-Value Coding规范兼容,必须实现以下方法:
- -insertObject:in<Key>AtIndex: or -insert<Key>:atIndexes: 两个必须实现一个,类似于 NSMutableArray 的方法 insertObject:atIndex: 和 insertObjects:atIndexes:
- -removeObjectFrom<Key>AtIndex: or -remove<Key>AtIndexes: 两个必须实现一个,类似于 NSMutableArray 的方法 removeObjectAtIndex: 和 removeObjectsAtIndexes:
- -replaceObjectIn<Key>AtIndex:withObject: or -replace<Key>AtIndexes:with<Key>: 可选的,如果在此类操作上有性能问题,就需要考虑实现之
collection accessor methods (for unordered to-many relationship)
Getter Unordered Accessors
- -countOf<Key> 必须的,类似于NSSet 的方法 count
- -enumeratorOf<Key> 必须实现的,类似于 NSSet 的方法 objectEnumerator
- -memberOf<Key>: 必须实现的,类似于 NSSet 的方法 member
Mutable Unordered Accessors
- -add<Key>Object: or -add<Key>: 两者必须实现一个,类似于 NSMutableSet 方法 addObject:
- -remove<Key>Object: or -remove<Key>: 两者必须实现一个,类似于 NSMutableSet 方法 removeObject:
- -intersect<Key>:. 可选的,类似于 NSSet 方法 intersectSet:
与KVC的关系
上面介绍了那么多Accessor,那它们分别与KVC有什么关系呢?
1. 为什么需要Accessor?
对于初学者也许会有这样的疑问。这个问题很简单,但是也很重要。Accessor解决的问题就是底层真正调用的方法和上层调用方法的映射。
假如类中有两个NSMutableArray类型的数据。mutableArrayValueForKey:会返回一个对真实数据的proxy,后续的操作都是对proxy的操作, 最终会转化成对类中Accessor方法的调用。这是大家都知道的。大家也知道:整个过程都是以key/index作为关键字进行映射的,其最后的fallback机制就是直接操作instance variable。那为什么不直接使用fallback机制作为主要逻辑,直接操作instance variable呢?问题的关键就在于KVO。如果各种调用都之间变成对instance variable的操作,developer将无法定制其KVO行为,比如谁observe某个对象,或者某部分对象!!当然还有其他的一些定制行为:比如支持Undo操作等。下面是Apple的官方文档对使用Accessor的好处:
You should use accessor methods rather than directly accessing state data because they provide an abstraction layer. Here are just two of the benefits that accessor methods provide:
- You don’t need to rewrite your code if the manner in which a property is represented or stored changes.
- Accessor methods often implement important behavior that occurs whenever a value is retrieved or set. For example, setter methods frequently implement memory management code and notify other objects when a value is changed.
2. KVC的search pattern是怎样的?
这个的详细路径可以参考Apple 的KVC Programming Guide。这里暂不详述。
Reference: Apple Key-Value Coding Programming Guide.