1,什么是IOS的KVO消息机制
IOS中的KVO机制(即Key-Value Obsering),很多地⽅方也称作"键/值观察"它提供⼀一种很⽅方便的⽅方法实现被观察者对象的属性被修改后,KVO会⾃自动的通知对应的观察者对象并调⽤用相应的⽅方法.当有变化发⽣生的时候,通知会直接发送到处于观察状态的对象。
2,KVO机制的实现⽅方法:
1,注册
将观察对象和被观察对象联系在⼀一起:
[dataCenter addObserver:self forKeyPath:@"musicData" options:(NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld) context:nil];
forKeyPath:观察者属性值;
options :观察键值变化的选择
context :传输的参数以上语句作⽤用是:将观察对象dataCenter和观者者self本类联系在⼀一起,只要dataCenter对象中的musicData键值有变化,则就会调⽤用观察者⽅方法。
2,实现观察者⽅方法
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{
//dosomeing;}
change存储变化的数据
3,移出观察
[dataCenter removeObserver:self forKeyPath:@"musicData"];
推荐阅读:
《ASIHTTPRequest的环境配置和使⽤用⽰示例》
《XCode出现Undefi゙ned symbols for architecture armv7错误》《IOS开发笔记(2)-序列化/反序列化》
《IOS开发笔记(3)-单例(Singleton)模式》
《IOS协议与委托》
《IOS的多线程操作NSOperation》
明确:在IOS的中,没有绝对的私有,包括⽅方法和变量。私有⽅方法通过类实例⽆无法直接访问,但因为有"编译时运⾏行"机制,我们可以通过类似perfromSelectoe的⽅方法来访问私有⽅方法。⽽而IOS中的私有变量通过所谓的KVC模式也是可以访问的。下⾯面特酷吧整理了IOS KVC模式的使⽤用⽅方法。(另外可以参考《IOS KVO键值观察模式》)
KVC模式就是key-value coding(键值编码),它的原理是使⽤用字符串标识,间接访问对象属性。关键⽅方法在NSKeyValueCodingprotocol中定义。KVC⽀支持类对象和内建基本数据类型。我们主要使⽤用到它的两对⽅方法:1,setValue:forKey,valueForKey;传⼊入NSString属性的名字2,setValue:forKeyPath,valueForKeyPath(传⼊入NSString属性的路径,xx.xx形式)
需要注意:
当通过KVC调⽤用对象时,⽐比如:
[self valueForKey:@"tekuba"];程序会⾃自动试图通过⼏几种不同的⽅方式解析这个调⽤用。⾸首先查找对象是否带有tekuba这个⽅方法以及getTekuba,_tekuba以及_getTekuba这⼏几种形式,如果没找到,会继续查找对象是否带有tekuba这个实例变量(iVar),如果还没有找到,程序会继续试图调⽤用 -(id) valueForUndefi゙nedKey:这个⽅方法。如果这个⽅方法还是没有被实现的话,程序会抛出⼀一个NSUndefi゙nedKeyException异常错误(待确认)。设计valueForUndefi゙nedKey:⽅方法的主要⽬目的是当你使⽤用-(id)valueForKey⽅方法从对象中请求值时,对象能够在错误发⽣生前,有最后的机会响应这个请求
请看下⾯面的⽰示例:
头⽂文件TekubaNet.h
#import<Foundation/Foundation.h>
@interface TekubaNet:NSObject
{
NSString *url;}
@end
实现⽂文件
#import"TekubaNet.h"
@implementation TekubaNet
@end这个TekubaNet类很简单,只有⼀一个url变量。这种情况我们是没有办法通过TekubaNet的类实例访问url的。下⾯面我们使⽤用KVC模式访问url。如下:
折叠 C/C++ Code 复制内容到剪贴板 | |
01.
02.
03.
04.
05.
06.
07.
08.
09.
|
int main (int argc, const char * argv[]) { } |
下⾯面我们对代码做⼀一些补充:定义⼀一个Webmaster类,特酷吧的博主:头⽂文件Webmaster.h#import<Foundation/Foundation.h>@interface Webmaster:NSObject
{
NSString *name;
}
@end
实现⽂文件
#import"Webmaster.h"@implementation Webmaster
@end将Webmaster添加到TekubaNet类,如下:#import<Foundation/Foundation.h>@interface TekubaNet:NSObject
{
Webmaster *webmaster;
NSString *url;}
@end
TekubaNet的实现⽂文件不变。下⾯面演⽰示使⽤用KVC模式访问TekubaNet中webmaster的name属性。
折叠 C/C++ Code 复制内容到剪贴板 | |
01.
02.
03.
04.
05.
06.
07.
08.
09.
10.
11.
12.
13.
14.
|
int main (int argc, const char * argv[]) { th*/ } NSLog(@"webmaster name: %@",name);[pool release]; |
另外需要注意,KVC还有⼀一个重要的特点就是⾃自动装箱拆箱功能:即KVC会根据字符串⾃自动的转型成适当的数据类型。例如:
@interface TekubaNet:NSObject
{
Webmaster *webmaster;NSString *url;
int runDay;
}
则我们还是可以通过之前的⽅方式访问:
[tekubaNet setValue:@"365" forKey:@"runDay"];
NSLog(@"tekubaNet runTime is %@",[tekubaNet valueForKey:@"runDay"]);虽然runDay是int型的,但我们⼀一样可以通过%@打印。
参考:KVO原理细节(摘⾃自⽹网络,链接遗失):
当KVC调⽤用之后,到底是怎样获取和设置类成员值的。
(1)setValue:forKey的搜索⽅方式:⾸首先搜索set<Key>:⽅方法。如果成员⽤用@property,@synthsize处理,因为@synthsize告诉编译器⾃自动⽣生成set<Key>:格式的setter⽅方法,所以这种情况下会直接搜索到。注意:这⾥里的<Key>是指成员名,⽽而且⾸首字母⼤大写。下同。上⾯面的setter⽅方法没有找到,如果类⽅方法accessInstanceVariablesDirectly返回YES(注:这是NSKeyValueCodingCatogery中实现的类⽅方法,默认实现为返回YES)。那么按_<key>,_is<Key>,<key>,is<key>的顺序搜索成员名。如果找到设置成员的值,如果没有调⽤用setValue:forUndefi゙nedKey:。
(2)valueForKey:的搜索⽅方式:
1. ⾸首先按get<Key>、<key>、is<Key>的顺序查找getter⽅方法,找到直接调⽤用。如果是bool、int等内建值类型,会做NSNumber的转换。
2. 上⾯面的getter没有找到,查找countOf<Key>、objectIn<Key>AtIndex:、<Key>AtIndexes格式的⽅方法。如果countOf<Key>和另外两个⽅方法中的⼀一个找到,那么就会返回⼀一个可以响应NSArray所有⽅方法的代理集合(collectionproxy object)。发送给这个代理集合(collection proxy object)的NSArray消息⽅方法,就会以countOf<Key>、objectIn<Key>AtIndex:、<Key>AtIndexes这⼏几个⽅方法组合的形式调⽤用。还有⼀一个可选的get<Key>:range:⽅方法。
3. 还没查到,那么查找countOf<Key>、enumeratorOf<Key>、memberOf<Key>:格式的⽅方法。如果这三个⽅方法都找到,那么就返回⼀一个可以响应NSSet所有⽅方法的代理集合(collection proxy object)。发送给这个代理集合(collection proxy object)的NSSet消息⽅方法,就会以countOf<Key>、enumeratorOf<Key>、memberOf<Key>:组合的形式调⽤用。
4. 还是没查到,那么如果类⽅方法accessInstanceVariablesDirectly返回YES,那么按_<key>,_is<Key>,<key>,is<key>的顺序直接搜索成员名。
5. 再没查到,调⽤用valueForUndefi゙nedKey:。