KVO原理與手動(dòng)調(diào)用
一、KVO
KVO 是 Objective-C 對(duì)觀察者模式(Observer Pattern)的實(shí)現(xiàn)。當(dāng)被觀察對(duì)象的某個(gè)屬性發(fā)生更改時(shí),觀察者對(duì)象會(huì)獲得通知。
二、KVO實(shí)現(xiàn)原理
- KVO是基于runtime機(jī)制實(shí)現(xiàn)的。
//創(chuàng)建Person對(duì)象,添加work屬性
@interface Person : NSObject
@property(nonatomic,copy) NSString * work;
@end
當(dāng)某個(gè)類(lèi)(Person)的屬性(work)對(duì)象第一次被觀察時(shí),系統(tǒng)就會(huì)在運(yùn)行期動(dòng)態(tài)地創(chuàng)建該類(lèi)的一個(gè)派生類(lèi)(NSKVONotifying_Person),在這個(gè)派生類(lèi)中重寫(xiě)基類(lèi)中任何被觀察屬性的setter 方法。派生類(lèi)在被重寫(xiě)的setter方法內(nèi)實(shí)現(xiàn)真正的通知機(jī)制

每個(gè)類(lèi)對(duì)象中都有一個(gè)isa指針指向當(dāng)前類(lèi),當(dāng)一個(gè)類(lèi)對(duì)象的第一次被觀察,那么系統(tǒng)會(huì)偷偷將isa指針指向動(dòng)態(tài)生成的派生類(lèi),從而在給被監(jiān)控屬性賦值時(shí)執(zhí)行的是派生類(lèi)的setter方法。
鍵值觀察通知依賴(lài)于NSObject 的兩個(gè)方法: willChangeValueForKey: 和 didChangevlueForKey:;在一個(gè)被觀察屬性發(fā)生改變之前, willChangeValueForKey:一定會(huì)被調(diào)用,這就 會(huì)記錄舊的值。而當(dāng)改變發(fā)生后,didChangeValueForKey:會(huì)被調(diào)用,繼而observeValueForKey:ofObject:change:context: 也會(huì)被調(diào)用。
派生類(lèi)中setter方法調(diào)用如下(偽代碼):
@implementation NSKVONotifying_Person
-(void)setWork:(NSString *)work{
[self willChangeValueForKey:@"work"];
NSLog(@"派生類(lèi)work");
[self didChangeValueForKey:@"work"];
}
@end
三、手動(dòng)調(diào)用KVO
在Person類(lèi)中添加類(lèi)方法:
+(BOOL)automaticallyNotifiesObserversOfWork{
return NO;
}
在觀察Person類(lèi)work屬性被觀察時(shí)的變化:

上述方法返回NO,則組織自動(dòng)調(diào)用鍵值觀察方法,在Person work setter方法里手動(dòng)調(diào)用:
-(void)setWork:(NSString *)work{
if (_work == work) {
return;
}
[self willChangeValueForKey:@"work"];
_work = work;
[self didChangeValueForKey:@"work"];
}
測(cè)試結(jié)果:
