KVO与KVC简单理解
///////////////////////////////////////我是该死的分割线/////////////////////////
KVO,即:Key-Value Observing,翻译过来就是键--值--观察.它提供一种机制,当指定的对象的属性被修改后,则对象就会接受到通知。简单的说就是每次指定的被观察的对象的属性被修改后,KVO就会自动通知相应的观察者了。
系统框架已经支持KVO,所以我们要做的就是如何用了.
1. 注册,指定被观察者的属性,//谁要观察,谁的属性改变通知你.
[stockForKVO addObserver:self forKeyPath:@"price" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:NULL];
//对象 添加观察者:我自己 哪个属性:price属性 可选项:模式|模式 上下文:空
这样就把注册,指定观察者属性都做完了
2. 实现回调方法//通知了你,你得做点事吧.
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void*)context
{
if([keyPath isEqualToString:@"price"])
{
myLabel.text = [stockForKVO valueForKey:@"price"];
}
}
//在这个方法里写通知你之后干的事,像例子说的那样,先判断是不是这个属性,然后再赋值.判断这一步不能少,如果同时好多人在观察,可能搞混淆.这里得引入和通知的区别了.
//KVO与通知区别:
通知:是一种广播机制,在实践发生的时候,通过通知中心对象,一个对象能够为所有关心这个时间发生的对象发送消息,两者都是观察者模式,不同在于KVO是被观察者直接发送消息给观察者,是对象间的直接交互,通知则是两者都和通知中心对象交互,对象之间不知道彼此
KVO使用:被观察着发生addobserver:forkeyPath:options:context:方法来添加观察者.然后只要被观察者的keypath值发生变化(注意单纯改变值不会调用此方法,只有通过getter和sett来改变值才会触发KVO),就会在观察者里调用方法observerValueForKeyPath:ofobject:change:context:因此实现此方法来对KVO发出的通知做出响应.
这些代码都是秩序在观察者里进行实现,被观察者不用添加任何代码,所以谁要监听谁要注册,然后对响应进行处理即可,使得观察者与被观察者完全解耦,运用很灵活很简便,但是KVO只能检测类中属性,并且属性名都是通过NSString来查找,编译器不会帮你检测对错和补全,纯手敲会比较容易出错
通知的使用:通知的发出是由通知中心来统一发出,而不同通知通过唯一标示名notifcationName来区分,标示名由发送通知的类来起.首先被观察者自己在必要的方法A里,通过方法postNotificationName:object:发出通知notificationName这样发送通知着这边的工作就完成了,每次A被调用,就会发送一次通知notificationName
然后谁要监听A的变化,就通过[NSNotificationCenter defaultCenter] 的方法addobserver:sslector:name:object为观察者注册监听name为notificationNmae的通知.
每次发出name为notificationNmae的通知时,注册监听后的观察着就会调用其自己定义的方法notificationselector来进行相应
NSNotification的特点,就是需要被观察者先主动发出通知,然后观察者注册监听后,再来进行响应,比KVO多了发送通知的一步,但是其优点是监听不局限属性的变化,还可以对多种多样的状态变化进行监听,监听范围广,使用灵活.
3. 移除观察//不会自动移除,需要手动移除
增加观察与取消观察是成对出现的,所以需要在最后的时候,移除观察者
///////////////////////////////////////我是该死的分割线//////////////////////////
KVC是KeyValueCoding的简称,翻译过来是键值编码,它是一种可以直接通过字符串的名字(key)来访问类属性(实例变量)的机制。而不是通过调用Setter、Getter方法(点语法)访问。
当使用KVO、Core Data、CocoaBindings、AppleScript(Mac支持)时,KVC是关键技术。
//
关键方法定义在:NSKeyValueCodingprotocol
The NSKeyValueCoding informal protocol defines a mechanism by which you can access the properties of an object indirectly by name (or key), rather than directly through invocation of an accessor method or as instance variables. Thus, all of an object’s properties can be accessed in a consistent manner.
这个键值编码非正式协议定义了一个机制通过你可以间接的获取一个对象的属性通过名字(或者叫key),而不是直接通过调用访问器方法或者实例变量.因此,一个对象的所有属性可以被存取用一个通用的方式.
The basic methods for accessing an object’s values are setValue:forKey:, which sets the value for the property identified by the specified key, and valueForKey:, which returns the value for the property identified by the specified key. The default implementation uses the accessor methods normally implemented by objects (or to access instance variables directly if need be).
这个基本方法对于访问一个对象的值是 setValue:forKey用来设置值对于可识别的属性通过规定的key,和valueForKey用来返回一个值对于可识别的属性通过规定的key.这个默认的实现使用了访问器方法正常的实现通过对象(或者通过实例变量如果需要的话).
Default Search Pattern for setValue:forKey://默认查找模式对于setValue:forKey
When the default implementation ofsetValue:forKey:is invoked for a property the following search pattern is used:
当这个默认实现setValue:forKey是属性调用模式是使用下列搜索模式
The receiver’s class is searched for an accessor method whose name matches the pattern set:.
接收器的类去搜索访问器方法的名字匹配这个设置模式.
If no accessor is found, and the receiver’s class method accessInstance VariablesDirectlyreturns YES, the receiver is searched for an instance variable whose name matches the pattern, _<key>,_is<key>,<key>,is<key>,in that order.
如果访问器方法没有找到,而且接受方法accessInstance VariablesDirectlyreturns返回yes,接受器将会搜索实例变量的名字匹配,在这种情况下.
If a matching accessor or instance variable is located, it is used to set the value. If necessary, the value is extracted from the object as described inRepresenting Non-Object Values.
如果匹配访问器方法或实例变量都加载了,它通常使用set the value.如果必要的话,值引出从对象像Representing Non-Object Values文档描述的一样.
If no appropriate accessor or instance variable is found,setValue:forUndefinedKey:is invoked for the receiver.
如果都没有找到的话,将会唤醒setValue:forUndefinedKey给接收器.//一般抛出异常,可重写.
//在字典转模型里,服务器返回的数据有些不想要就重写这个方法.
Default Search Pattern for valueForKey://默认搜索模式对于valueForKey
When the default implementation of valueForKey:is invoked on a receiver, the following search pattern is used:
//当默认实现valueForKey是调用在接收器,通常使用以下搜索模式
Searches the class of the receiver for an accessor method whose name matches the pattern get<key>,<key>,is<key>, in that order. If such a method is found it is invoked. If the type of the method's result is an object pointer type the result is simply returned. If the type of the result is one of the scalar types supported by NSNumber conversion is done and an NSNumber is returned. Otherwise, conversion is done and an NSValue is returned. Results of arbitrary types are converted to NSValue objects, not just NSPoint,NSRange,NSRect, and NSSize types).
搜索接受者类从访问器方法的名字匹配参数get<key>,<key>,is<key>,在那种情况下.如果发现这个方法被调用了,如果这个方法飞返回类型是一个对象指针类型,这个结果简单的返回.如果这个结果类型是数量的一种,将转换为NSNumber返回,否则,转换NSValue返回.任意的结果类型都是转换成NSValue类了,不只是NSPoint,NSRange,NSRect, and NSSize types.
Otherwise (no simple accessor method is found), searches the class of the receiver for methods whose names match the patterns countOf and objectInAtIndex:(corresponding to the primitive methods defined by the NSArray class) andAtIndexes:(corresponding to the NSArray method objectsAtIndexes:). If the countOf method and at least one of the other two possible methods are found, a collection proxy object that responds to all NSArray methods is returned. Each NSArray message sent to the collection proxy object will result in some combination of countOf,objectInAtIndex:, andAtIndexes:messages being sent to the original receiver of valueForKey:. If the class of the receiver also implements an optional method whose name matches the pattern get:range:that method will be used when appropriate for best performance.
否则(没有找到简单访问器方法),搜索这个接受器的类从方法匹配参数countOfand objectInAtIndex(相当于去用原始方法定义在NSArray 类里)andAtIndexes(相当于去用这个NSArray方法 andAtIndexes).如果countOf方法至少一到两个可能的方法被找到,一个集合代理对象对于所有的NSArray methods将会被返回,每一个NSArray 消息发送给集合代理对象将会返回countOf,objectInAtIndex,andAtIndexes组合.消息将要发送给valueForKey的原始接受者,如果这个接受者的类也实现一个可选方法,是名字匹配参数get:range:,那方法将会使用当合适为了做好的执行.
Otherwise (no simple accessor method or set of array access methods is found), searches the class of the receiver for a threesome of methods whose names match the patterns countOf,enumeratorOf, and memberOf:(corresponding to the primitive methods defined by theNSSet class). If all three methods are found, a collection proxy object that responds to all NSSet methods is returned. Each NSSet message sent to the collection proxy object will result in some combination of countOf,enumeratorOf, and memberOf:messages being sent to the original receiver of valueForKey:.
否则(访问器方法和set of array access methods都没有找到),搜索接收器的类将从一个三人组方法,是名字匹配模式countOf,enumeratorOf, and memberOf(相当于使用原始方法定义在NSSet类里),如果都三个方法都找到了,一个集合代理对象将会响应所有的NSSet方法并返回.每一个NSSet 消息发送给集合代理对象将会生成countOf,enumeratorOf, andmemberOf组合,消息将会被发送去这的valueForKey原始接受器.
Otherwise (no simple accessor method or set of collection access methods is found), if the receiver's class method accessInstanceVariablesDirectly returnsYES, the class of the receiver is searched for an instance variable whose name matches the pattern_,_is,, oris, in that order. If such an instance variable is found, the value of the instance variable in the receiver is returned. If the type of the result is one of the scalar types supported by NSNumber conversion is done and an NSNumber is returned. Otherwise, conversion is done and an NSValue is returned. Results of arbitrary types are converted toNSValueobjects, not justNSPoint,NSRange,NSRect, andNSSizetypes.
否则(没有找到简单访问器方法和set of collection access methods的一种),如果接收器的类方法
accessInstanceVariablesDirectly返回yes,这个接收器的类将会搜索实例变量,是名字匹配参数
_<key>,_is<key>,<key>,is<key>,在这种情况下.如果找到了实例变量,这个实例变量的值将会被返回.如果结果的类型是数量类型的一种,将转换成NSNumber并返回,否则,转换为NSValue返回.任意的结果类型都是转换成NSValue类了,不只是NSPoint,NSRange,NSRect, and NSSize types.
If none of the above situations occurs, returns a result the default implementation invokes valueForUndefinedKey:.
如果没有出现上述情况,返回默认实现结果调用valueForUndefinedKey.
KVC支持类对象和内建基本数据类型。
获取值
valueForKey:,传入NSString属性的名字。
valueForKeyPath:,传入NSString属性的路径,xx.xx形式。
valueForUndefinedKey它的默认实现是抛出异常,可以重写这个函数做错误处理。
修改值
setValue:forKey:
setValue:forKeyPath:
setValue:forUndefinedKey:
setNilValueForKey:当对非类对象属性设置nil时,调用,默认抛出异常。
一对多关系成员的情况
mutableArrayValueForKey:有序一对多关系成员 NSArray
mutableSetValueForKey:无序一对多关系成员 NSSet