设为首页 加入收藏

TOP

object-c编程tips-KVO,KVC浅析(三)
2015-01-22 20:57:07 来源: 作者: 【 】 浏览:20
Tags:object-c 编程 tips-KVO KVC 浅析
ueForKeyPath是抛出异常。这是一个好的编程实践,因为它可以使错误更早的暴露出来。最好不要提供一个空的实现,这样可能由于编程者的错误而没有实现observeva lueForKeyPath,但是编译器并不会将这种错误表现出来。

3, 常用的类框架图

?

?

4, 在哪里添加和删除观察者?

添加和删除观察者的操作最好能够封装到目标或者观察者类体内,而不要如demo例子中所使用的使用一个driver进行操作(我主要意图是希望使类结构清晰点)。一般情况下可在init中加入,在dealloc中删除。这样使用者不会因为编程的疏忽导致忘记最后的删除操作。

七,KVO的实现

例如demo工程KVOPrinciple

KVO是通过叫isa-swizzling技术实现的,基本的流程就是编译器自动为被观察对象创造一个派生类,并将被观察对象的isa指向这个派生类。如果用户注册了对某此目标对象的某一个属性的观察,那么此派生类会重写这个方法,并在其中添加进行通知的代码。这个需要OC运行时候的流程有一个基本了解。OC在发送消息的时候,会通过isa指针找到当前对象所属的类对象,而类对象中保存着当前对象的实例方法,因此在向此对象发送消息时候,实际上是发送到了派生类对象的方法,又由于编译器对派生类的方法进行了override,并添加了通知代码,因此会向注册的对象发送通知。注意派生类只重写注册了观察者的属性方法。

?

举例:

有一个Person类,它有三个属性firstName, lastName, personId,它是被观察对象。有一个PersonObserver类,它观察firstName和lastName,不观察personId。

理论来说,派生类会覆盖基类的setFirstName和setLastName方法,不覆盖setPersonId方法。通过运行时函数object_getClass(p)访问此person对象,会得到一个名字为NSKVONotifying_Person的类对象,如果直接通过[p class]方法访问,那么会看到它依然为person对象,这是因为派生类同样重写了class函数,当向p发送class消息时候,同样是找到了派生类的class方法。

通过分别打印不同类对象的函数表进行测试。对于派生类和基类取得其setFirstName的IMP实现,然后进行直接调用比较。现在对于基类使用IMP访问会崩溃,暂未知原因。对于派生类使用其IMP实现,确实可以正常发送通知,这表明确实是使用的派生类的实现。


八,总结

1,简介

键值编码是使用String标识符间接获取对象属性的机制。它是Cocoa编程的基础,包括Cocoa Data,应用脚本化,绑定技术,属性声明。脚本化和绑定技术是专门为OSX的Cocoa而用,你可以使用键值编码去简化编程代码,Jastor就使用统一的setValueForKey,以及valueForKey。

2,访问对象属性和KVC

2.1,KVC常用以下四个方法:

-(id)valueForKey:(NSString *)key;

-(void)setValue:(id)value forKey:(NSString *)key; - -(id)valueForKeyPath:(NSString*)keyPath;

- (void)setValue:(id)value forKeyPath:(NSString *)keyPath;

KVC通过字符串的key或者keypath定位对象的属性。Key有命名管理,以ASCII编码,小写字母开头,无空格,它一般就是属性的名字。KeyPath是一个用点分割的字符串用来逐层遍历最深层的属性值。

?

如上例子:

[employee1setValue:@”lpstudy” forKey:@”name”];

[employee1setValue:@[employee1, employee2, employee3]forKeyPath:@”manager.directerPorts”];

2.2,使用访问器方法

如果有,访问器方法依然是有效的。如果没有相应的访问器方法,可以使用上面的setValue和valueForKey直接读取对象的属性值。

2.3,具有KVC能力

如何使一个类具有KVC功能,必须满足下列的其中一个:

l 类使用key声明了属性

@property (nonatomic ,readonly,strong) NSString *personName;

l 它实现了key名字的get方法和set方法。如果返回bool类型,isKey方法。

l 声明了一个实例变量,key或者_key

需要注意

l valueForKey和valueForKeyPath 返回指定key,keyPath的value值。如果不存在此key,会调用valueForUndefinedKey:。它的默认实现是抛出NSUndefinedKeyException;子类可以复写这种行为。

l 尝试给一个非对象类型设置nil。对象默认调用setNilValueForKey此方法默认抛出NSInvalidArgumentException.你的程序可以覆盖这个方法给一个默认值,然后 setValue:forKey: 设置新值。

l 鉴权机制validatePersonName

2.4,搜索方式

以下选自于网络,我并没有进行相关的测试。

setValue:forKey的搜索方式:

1,首先搜索set :方法。如果成员用@property,@synthsize处理,因为@synthsize告诉编译器自动生成set :格式的setter方法,所以这种情况下会直接搜索到。

2,上面的setter方法没有找到,如果类方法accessInstanceVariablesDirectly返回YES(注:这是NSKeyValueCodingCatogery中实现的类方法,默认实现为返回YES),则按_ ,_is ,is 的顺序搜索成员的名值。

3,如果找到则设置成员的值,没有找到则调用setValue:forUndefinedKey:。

valueForKey的搜索方式

1.,按get 、is 的顺序查找getter方法,找到直接调用。如果是bool、int等内建值类型,会做NSNumber的转换,如果是其他类似于struct结构体类型则会进行NSValue的转换。

2,否则查找countOf 、objectIn AtIndex:、 AtIndexes格式的方法。 如果countOf 和另外两个方法中的一个找到,那么就会返回一个可以响应NSArray所有方法的代理集合(collection proxy object)。发送给这个代理集合(collection proxy object)的NSArray消息方法,就会以countOf 、objectIn AtIndex:、 AtIndexes这几个方法组合的形式调用。还有一个可选的get :range:方法。

3,还没找到则继续查找countOf 、enumeratorOf 、memberOf :格式的方法。 如果这三个方法都找到,那么就

首页 上一页 1 2 3 4 下一页 尾页 3/4/4
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇object-c编程tips-jastor自动解析 下一篇动态映射objective-c的对象方法修..

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: