options是KVO中常见的参数,然而通常只是将它固定为“NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld”来使用却不知道到底这个参数有什么用。由此本文通过一个例子来描述该参数的实际表现。
NSKeyValueObservingOptions是options的类型(
- (void)addObserver:(NSObject *)observer
forKeyPath:(NSString *)keyPath
options:(NSKeyValueObservingOptions)options
context:(void *)context
)
首先看头文件中的定义:
typedefNS_OPTIONS(NSUInteger, NSKeyValueObservingOptions) {
/* Whether the change dictionaries sent in notifications should contain NSKeyValueChangeNewKey and NSKeyValueChangeOldKey entries, respectively.
*/
NSKeyValueObservingOptionNew =0x01,
NSKeyValueObservingOptionOld =0x02,
/* Whether a notification should be sent to the observer immediately, before the observer registration method even returns. The change dictionary in the notification will always contain an NSKeyValueChangeNewKey entry if NSKeyValueObservingOptionNew is also specified but will never contain an NSKeyValueChangeOldKey entry. (In an initial notification the current value of the observed property may be old, but it's new to the observer.) You can use this option instead of explicitly invoking, at the same time, code that is also invoked by the observer's -observeValueForKeyPath:ofObject:change:context: method. When this option is used with -addObserver:toObjectsAtIndexes:forKeyPath:options:context: a notification will be sent for each indexed object to which the observer is being added.
*/
NSKeyValueObservingOptionInitial NS_ENUM_AVAILABLE(10_5,2_0) =0x04,
/* Whether separate notifications should be sent to the observer before and after each change, instead of a single notification after the change. The change dictionary in a notification sent before a change always contains an NSKeyValueChangeNotificationIsPriorKey entry whose value is [NSNumber numberWithBool:YES], but never contains an NSKeyValueChangeNewKey entry. You can use this option when the observer's own KVO-compliance requires it to invoke one of the -willChange... methods for one of its own properties, and the value of that property depends on the value of the observed object's property. (In that situation it's too late to easily invoke -willChange... properly in response to receiving an -observeValueForKeyPath:ofObject:change:context: message after the change.)
When this option is specified, the change dictionary in a notification sent after a change contains the same entries that it would contain if this option were not specified, except for ordered unique to-many relationships represented by NSOrderedSets.For those, for NSKeyValueChangeInsertion and NSKeyValueChangeReplacement changes, the change dictionary for a will-change notification contains an NSKeyValueChangeIndexesKey (and NSKeyValueChangeOldKey in the case of Replacement where the NSKeyValueObservingOptionOld option was specified at registration time) which give the indexes (and objects) which *may* be changed by the operation.The second notification, after the change, contains entries reporting what did actually change.For NSKeyValueChangeRemoval changes, removals by index are precise.
*/
NSKeyValueObservingOptionPrior NS_ENUM_AVAILABLE(10_5,2_0) =0x08
};
可以很清楚的看到,其中包含了四种值,分别为:
NSKeyValueObservingOptionNew:提供更改前的值
NSKeyValueObservingOptionOld:提供更改后的值
NSKeyValueObservingOptionInitial:观察最初的值(在注册观察服务时会调用一次触发方法)
NSKeyValueObservingOptionPrior:分别在值修改前后触发方法(即一次修改有两次触发)
以下是一个简单的测试案例:
测试代码
将options修改为NSKeyValueObservingOptionNew得到测试结果:
2016-07-04 19:18:29.265 testForKVO[50887:35316085] turn1
2016-07-04 19:18:29.265 testForKVO[50887:35316085] kind: 1
2016-07-04 19:18:29.266 testForKVO[50887:35316085] new: turn1
2016-07-04 19:18:29.266 testForKVO[50887:35316085] turn2
2016-07-04 19:18:29.266 testForKVO[50887:35316085] kind: 1
2016-07-04 19:18:29.266 testForKVO[50887:35316085] new: turn2
可以看到观察被触发2次,在change对象中包含key为new的值,并且为stringA的最新值
将options修改为NSKeyValueObservingOptionOld得到测试结果:
2016-07-04 19:19:14.562 testForKVO[50912:35317211] turn1
2016-07-04 19:19:14.562 testForKVO[50912:35317211] kind: 1
2016-07-04 19:19:14.562 testForKVO[50912:35317211] old: turn0
2016-07-04 19:19:14.563 testForKVO[50912:35317211] turn2
2016-07-04 19:19:14.563 testForKVO[50912:35317211] kind: 1
2016-07-04 19:19:14.563 testForKVO[50912:35317211] old: turn1
可以看到观察被触发2次,在change对象中包含key为old的值,并且为stringA被修改前的值
将options修改为NSKeyValueObservingOptionInitial得到测试结果:
//注册观察服务时
2016-07-04 19:20:08.003 testForKVO[50938:35318482] turn0
2016-07-04 19:20:08.004 testForKVO[50938:35318482] kind: 1
//self.stringA=@"turn1";
2016-07-04 19:20:08.004 testForKVO[50938:35318482] turn1
2016-07-04 19:20:08.004 testForKVO[50938:35318482] kind: 1
//self.stringA=@"turn2";
2016-07-04 19:20:08.004 testForKVO[50938:35318482] turn2
2016-07-04 19:20:08.005 testForKVO[50938:35318482] kind: 1
可以看到观察被触发3次,在观察服务注册时,执行了一次触发
将options修改为NSKeyValueObservingOptionPrior得到测试结果:
2016-07-04 19:20:47.936 testForKVO[50962:35319521] turn0
2016-07-04 19:20:47.937 testForKVO[50962:35319521] kind: 1
2016-07-04 19:20:47.937 testForKVO[50962:35319521] notificationIsPrior: 1
2016-07-04 19:20:47.937 testForKVO[50962:35319521] turn1
2016-07-04 19:20:47.937 testForKVO[50962:35319521] kind: 1
2016-07-04 19:20:47.937 testForKVO[50962:35319521] turn1
2016-07-04 19:20:47.938 testForKVO[50962:35319521] kind: 1
2016-07-04 19:20:47.938 testForKVO[50962:35319521] notificationIsPrior: 1
2016-07-04 19:20:47.938 testForKVO[50962:35319521] turn2
2016-07-04 19:20:47.938 testForKVO[50962:35319521] kind: 1
可以看到观察被触发4次,从turn0->turn1改变前后触发2次,turn1->turn2改变前后触发2次
其它
将options修改为 0 得到测试结果:
2016-07-04 19:50:43.925 testForKVO[51293:35351701] turn1
2016-07-04 19:50:43.925 testForKVO[51293:35351701] kind: 1
2016-07-04 19:50:43.925 testForKVO[51293:35351701] turn2
2016-07-04 19:50:43.925 testForKVO[51293:35351701] kind: 1
将options修改为
NSKeyValueObservingOptionNew|
NSKeyValueObservingOptionOld|
NSKeyValueObservingOptionInitial|
NSKeyValueObservingOptionPrior得到测试结果:
//注册观察服务时
2016-07-04 19:33:12.326 testForKVO[51133:35333070] turn0
2016-07-04 19:33:12.326 testForKVO[51133:35333070] kind: 1
2016-07-04 19:33:12.326 testForKVO[51133:35333070] new: turn0
//self.stringA=@"turn1";
2016-07-04 19:33:12.327 testForKVO[51133:35333070] turn0
2016-07-04 19:33:12.327 testForKVO[51133:35333070] kind: 1
2016-07-04 19:33:12.327 testForKVO[51133:35333070] old: turn0
2016-07-04 19:33:12.327 testForKVO[51133:35333070] notificationIsPrior: 1
2016-07-04 19:33:12.327 testForKVO[51133:35333070] turn1
2016-07-04 19:33:12.327 testForKVO[51133:35333070] kind: 1
2016-07-04 19:33:12.327 testForKVO[51133:35333070] old: turn0
2016-07-04 19:33:12.327 testForKVO[51133:35333070] new: turn1
//self.stringA=@"turn2";
2016-07-04 19:33:12.328 testForKVO[51133:35333070] turn1
2016-07-04 19:33:12.328 testForKVO[51133:35333070] kind: 1
2016-07-04 19:33:12.328 testForKVO[51133:35333070] old: turn1
2016-07-04 19:33:12.328 testForKVO[51133:35333070] notificationIsPrior: 1
2016-07-04 19:33:12.328 testForKVO[51133:35333070] turn2
2016-07-04 19:33:12.328 testForKVO[51133:35333070] kind: 1
2016-07-04 19:33:12.328 testForKVO[51133:35333070] old: turn1
2016-07-04 19:33:12.328 testForKVO[51133:35333070] new: turn2
参考资料:
ios里的KVO模式
00000002