KVO:
key value observer,它提供一種當指定的對象屬性被修改之後,則其觀察者會接收到通知的機制。也就是說:被指定的觀察對象的屬性被修改之後,KVO就會自動通知相應的觀察者了。這也是一種設計模式,用於兩個類之間的解耦合,尤其是業務邏輯和試圖控制器之間的解耦;
self.p1 = [[Person alloc]init];
self.p1.name = @"111";
/*
- (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(nullable void *)context;
1 觀察者,負責處理監聽事件的對象
2 觀察的屬性
3 觀察的選項
*NSKeyValueObservingOptions
NSKeyValueObservingOptionNew = 0x01, 新值
NSKeyValueObservingOptionOld = 0x02, 舊值
NSKeyValueObservingOptionInitial 初始值
NSKeyValueObservingOptionPrior 之前的值
4 上下文
*/
[self.p1 addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionOld|NSKeyValueObservingOptionNew context:nil];
//self.p1.name = @"123";
必須實現方法
//這個方法是NSObject的,任何對象都可以作爲觀察者
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context
{
NSLog(@"監聽到了%@的%@屬性發生了改變", object, keyPath);
NSLog(@"%@", change);
}
KVO的實現原理:
KVO是基於Runtime機制實現的,當某個類的屬性對象第一次被觀察時,系統會在運行期動態的創建該類的派生類,在這個派生類中重寫基類中任何被觀察屬性的setter方法;
例子:
原生類爲Person,那麼在運行期runtime會生成一個派生類:NSKVONotifying_person,繼承自person類,每個類對象都有一個isa指針指向當前類,當一個類對象第一次被觀察時,那麼系統會將isa指針指向動態生成的這個派生類,從而在給被監控的屬性賦值時執行的是派生類的setter方法。KVO依賴於NSObject的兩個方法:
1> willChangeValueForKey 在一個被觀察的屬性改變之前調用,記住這個值。
2> didChangeValueForKey 在被觀察的屬性之後調用,纔會調用observerValueForkey
解釋:當person的name屬性改變時,person對象的isa指針會指向NSKVONotifying_person,
-(void)setName:(NSString *)name
{
//這兩個方法的底層會調用-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(id *)change context:(void *)context
[self willChangeValueForKey:@""];
[self didChangeValueForKey:@" "];
}