允许开发者通过名字访问对象属性,而无需调用明确的存取方法。这样,开发者就能在运行时确定属性的绑定,而不是在编译时确定。比如说,我们能用[object valueForKey:someProperty]
表达式来请求由字符串变量,在从数据库读取的数据赋值时有用,在使用服务端返回的json的时候也有用。
KVC标准
赋值方法和取值方法的KVC标准遵循以下模式:赋值方法是set<Value>:
,而取值方法就是简单的<value>
。在这两种情况下,<value>
部分都必须替换成你要访问的属性名。该属性必须是名字符合驼峰命名法的成员变量。
KVO
利用键值观察(Key Value Observing),你可以自动观察其他对象的变化。因此,当一个对象改变状态时你就会得到通知,比如用户通过应用中的设置面板改变了设置时。通过键值 观察,利用该设置的窗体和其他对象在用户改变该设置时,都可以自动得到通知。你不需要手动告诉其他对象进行更新。它们会自动收到新值并执行适当的操作。这 极其强大。设置是该技术最强大的应用之一,此外,Cocoa框架中的核心数据和其他技术也利用了键值观察实现了一些奇妙的功能。
要使用键值观察,被观察的对象必须对所观察的特性使用符合KVC标准的存取器方法。第二,想要观察变化的对象,也就是观察者,必须实现一个接收通知的特殊方法。该方法是-observeValue:forKeyPath:ofObject:change:context:
。该方法在值变化时被调用并可以配置成同时接收新值和原值以及其他自定义的信息。
最后,观察者通过调用-addObserver:forKeyPath:options:context:
方法针对被观察对象进行注册。调用该方法,告诉对象要观察的KVC键路径以及希望看到的变化,并提供一个在收到变化通知时可以传回的上下文对象。
但观察者完成这些配置后,键路径指定的属性的任何变化都可以自动调用观察者的回调方法。在观察者完成对被观察对象的观察后,必须将自己移除。如果没有做到这点并且观察者之后就释放了,将来向该观察者发送通知时可能会导致应用崩溃。
[obj addObserver:self forKeyPath:@"memberVariable" options:(NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld) context:NULL];
Observer
参数通常是self
,这是在被观察值变化时收到通知的对象。键路径参数指定想要观察的特性的键路径。options
参数指定一些标记来告诉KVO你希望变化如何传给你。这些值可以通过|操作符进行或操作。传入的可能值如表6-2所示。
传入的可能值
值 | 功 能 |
---|---|
NSKeyValueObservingOptionNew |
作为变更信息的一部分发送新值 |
NSKeyValueObservingOptionOld |
作为变更信息的一部分发送旧值 |
NSKeyValueObservingOptionInitial |
在观察者注册时发送一个初始更新 |
NSKeyValueObservingOptionPrior |
在变更前后分别发送变更,而不只在变更后发送一次 |
使用KVO的第二步就是编写观察者的回调方法。
-(void)observeValueForKeyPath:(NSString*)inKeyPath ofObject:(id)inObject change:(NSDictionary*)inChange context:(void*)inCtx;{if([inKeyPath isEqualToString:@"memberVariable"]){NSString*newValue =[inChange objectForKey:NSKeyValueChangeNewKey];// 对新值进行一些处理}elseif([inKeyPath isEqualToString:@"..."]){}[super observeValueForKeyPath:inKeyPath ofObject:inObject change:inChange context:inCtx];}
可以从该方法看出,要做的第一件事情就是找出被观察对象中变化的特性。该方法自动传入一个对象参数,告诉你哪个对象向你发送通知。通过对键路径的传入值使用-isEquals
方法,你可以准确地确定对象的什么特性发生了改变。Key
参数仅仅是一个字符串,和对KVC使用时一样。因此,可以使用NSString
方法-isEqualToString:
来确定该通知所对应的键路径。
在确定了对象的哪个特性发生变化后,你可以执行任何合适的操作。实际的变化通过change
参数传递给你。该参数是一个NSDictionary
对象,包括和你注册成为观察者时所请求的变化信息相关的键和值。
键 | 值 |
---|---|
NSKeyValueChangeKindKey |
指定变化类型的NSNumber |
NSKeyValueChangeNewKey |
新值 |
NSKeyValueChangeOldKey |
原值 |
NSKeyValueChangeIndexeskey |
如果NSKeyValueChangeKindKey 是NSKeyValueChangeInsertion 、NSKeyValueChangeRemoval 、NSKeyValueChangeReplacement 之一,该值就包含变化值的索引 |
NSKeyValueChangeNotificationIsPriorKey |
和NSKeyValueChangeOptionPrior 结合使用来表示这是“之前”的通知 |
可以看出,如果选择同时接收原值和新值,两个都会在变化参数中提供,通过合适的键就可以访问到。从变化字典中获取到值之后,就可以在对象中使用它执行任何需要的操作。
记住KVC必须使用对象来发送值——不能直接使用标量和结构体。因此,如果所观察的值是标量或者结构体,所接收的值就分别是NSNumber
或NSValue
类型的。因此,必须从该值中提取出实际需要的标量或者结构体值。上述示例代码就展示了这一点。