前言
KVO的用法前面已經講過了疯溺,不懂得可以去看我的KVC、KVO探識(一),希望會對你有幫助囱嫩。今天主要講KVC嗅辣、KVO的底層實現(xiàn)……因為之前我也不懂,所以很有必要記錄一下挠说。
準備工作
KVO是基于觀察者設計模式來實現(xiàn)的澡谭。
觀察者模式:一個目標對象管理所有依賴于它的觀察者對象,并在它自身的狀態(tài)改變時主動通知觀察者對象损俭。這個主動通知通常是通過調用各觀察者對象所提供的接口方法來實現(xiàn)的蛙奖。觀察者模式較完美地將目標對象與觀察者對象解耦。
手動實現(xiàn)鍵值觀察(代碼示例)
被觀察的對象Target(重寫setter/getter方法)
Target.h
@interface Target : NSObject
{
int age;
}
// for manual KVO
- age- (int) age;
- (void) setAge:(int)theAge;
@end
Target.m
@implementation Target
- (id) init{
self = [super init];
if (nil != self) {
age = 10;
}
return self;
}
// for manual KVO - age
- (int) age{
return age;
}
- (void) setAge:(int)theAge{
[self willChangeValueForKey:@"age"];
age = theAge;
[self didChangeValueForKey:@"age"];
}
+ (BOOL) automaticallyNotifiesObserversForKey:(NSString *)key {
if ([key isEqualToString:@"age"]) {
return NO;
}
return [super automaticallyNotifiesObserversForKey:key]**;
}
@end
首先杆兵,需要手動實現(xiàn)屬性的 setter 方法雁仲,并在設置操作的前后分別調用 **willChangeValueForKey: **和 didChangeValueForKey方法,這兩個方法用于通知系統(tǒng)該 key 的屬性值即將和已經變更了琐脏;
其次攒砖,要實現(xiàn)類方法 automaticallyNotifiesObserversForKey,并在其中設置對該 key 不自動發(fā)送通知(返回 NO 即可)日裙。這里要注意吹艇,對其它非手動實現(xiàn)的 key,要轉交給 super 來處理昂拂。
實現(xiàn)原理
KVO的實現(xiàn)是基于runtime運行時的受神,下面就來詳細介紹一下原理:還是這張圖:
- 當某個類的對象第一次被觀察時,系統(tǒng)就會在運行期動態(tài)地創(chuàng)建該類的一個派生類格侯,在這個派生類中重寫基類中任何被觀察屬性的 setter 方法鼻听。
- 派生類在被重寫的 setter 方法中實現(xiàn)真正的通知機制,就如前面手動實現(xiàn)鍵值觀察那樣联四。這么做是基于設置屬性會調用 setter 方法撑碴,而通過重寫就獲得了 KVO 需要的通知機制。當然前提是要通過遵循 KVO 的屬性設置方式來變更屬性值朝墩,如果僅是直接修改屬性對應的成員變量醉拓,是無法實現(xiàn) KVO 的。
- 同時派生類還重寫了 class 方法以“欺騙”外部調用者它就是起初的那個類鱼辙。然后系統(tǒng)將這個對象的 isa 指針指向這個新誕生的派生類廉嚼,因此這個對象就成為該派生類的對象了玫镐,因而在該對象上對 setter 的調用就會調用重寫的 setter倒戏,從而激活鍵值通知機制。此外恐似,派生類還重寫了 dealloc 方法來釋放資源杜跷。
歡迎關注我的個人微信公眾號,免費送計算機各種最新視頻資源!你想象不到的精彩葛闷!