最近两天时间比较充裕,然后这个月的工作安排也已经完成,所以拿点时间来对Cocoa一些问题填个坑,毕竟自己真的掉进去了啊!o(╯□╰)o
起因也是那天同事要实现一个垮多对象之间的数据传递,然后我就说可以用kvo啊(话说我也用的不多,就这样把别人带进去了),然后就是他就掉坑里了,发现对一个属性类型为 NSArray 做keyValuePath (eg:“prop.count”) 根本无法监控到改数组发生改变,原因是 用错了方法,针对数组,应该使用
- (NSMutableArray *)mutableArrayValueForKey:(NSString *)key;
因为监控的是setter 方法,只有在对属性赋值 prop = "pro"的前后,分别调用 willChangeValueForKey: 和 didChangeValueForKey: ,才会触发通知。那个坑就这么填完了!
为了以后少坑自己,所以今天对kvo多做了一些了解,就稍微记录下!
先上图:
就拿人来说事吧
@interface Persion :NSObject
@property(nonatomic,assign) age;
@property(nonatomic,copy) name;
@end
然后在 Person 实例对象添加了一个观察者
Person *hecv = [Person new];
[hecv addObserver:observer forKeyPath:@"age" options:0 context:NULL];
当这个 Person对象被第一次添加观察者的时候,其实他派生了一个类 SubPerson,(Person和Subperson 都是类对象,不是对应的实例),这个派生类在实现上,发生了一些变化;
- 重写了类对象的 class 方法,让他自己的isa 指针指向 父类的isa指针指向的地址。目的是欺骗外部调用者,让他们以为本派生类就是基类,这个实现有说是系统处理的。
- 重写了父类所有被观察的 setter 方法,这里来说就是 setage: 方法。
目的是在外部调用 Person实例对象的 setter 方法的时候,其实他找的类对象,并不是原来的 Person类对象,而是subPerson 类对象,(这个对象有点特殊,类名应该是 NSKVONotifying_Person) ,从而在setter 方法中可以通过 willChangeValueForKey: 和didChangeValueForKey: 两个方法来监控属性的变化。 - dealloc 方法用来处理内存问题
- _isKVOA 这个私有方法应该是用来表示这个类对象是KVO的
个人的理解大概就是这么多了,苹果的官方 programming guid 是这样描述的。
官方kvo实现细节说明所以总的来说哦,kvo这个东西是基于强大的runtime的好技术,应该说是语言的所带来的产品吧!
对博文中的一些不太理解的问题做了分析,可能因为对runtime的一些理解并不透彻,造成偏颇,看客请轻拍砖和指正!要更好的理解,请细读楼上链接的博文!