KVC是怎么訪問屬性的?KVO怎么實(shí)現(xiàn)的库糠?

KVC是怎么訪問屬性的

  • KVC在某種程度上提供了替代存取方法(訪問器方法)的方案滤灯,不過存取方法終究是個(gè)好東西,以至于只要有可能曼玩,KVC也盡可能先嘗試使用存取方法訪問屬性鳞骤。當(dāng)使用KVC訪問屬性時(shí),它內(nèi)部其實(shí)做了很多事:
  • 首先查找有無<property>黍判,set<property>豫尽,is<property>等property屬性對應(yīng)的存取方法,若有顷帖,則直接使用這些方法;
  • 若無美旧,則繼續(xù)查找<property>,_get<property>贬墩,_set<property>等方法榴嗅,若有就使用;
  • 若查詢不到以上任何存取方法陶舞,則嘗試直接訪問實(shí)例變量<property>嗽测,<property>;
  • 若連該成員變量也訪問不到,則會在下面方法中拋出異常唠粥。之所以提供這兩個(gè)方法疏魏,valueForUndefinedKey:和setValue:forUndefinedKey:方法,,就是讓你在因訪問不到該屬性而程序即將崩掉前,供你重寫晤愧,在內(nèi)做些處理大莫,防止程序直接崩掉。

KVO是什么官份?

  • Key-Value Obersver只厘,即鍵值觀察。它是觀察者模式的一種衍生舅巷「嵛叮基本思想是,對目標(biāo)對象的某屬性添加觀察悄谐,當(dāng)該屬性發(fā)生變化時(shí)介评,會自動(dòng)的通知觀察者库北。這里所謂的通知是觸發(fā)觀察者對象實(shí)現(xiàn)的KVO的接口方法爬舰。KVO是解決model和view同步的好法子。另外寒瓦,KVO的優(yōu)點(diǎn)是當(dāng)被觀察的屬性值改變時(shí)是會自動(dòng)發(fā)送通知的情屹,這比通知中心需要post通知來說,簡單了許多杂腰。

  • 首先給目標(biāo)對象的屬性添加觀察:

 - (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(nullable void *)context;
  • 實(shí)現(xiàn)下面方法來接收通知垃你,需要注意各個(gè)參數(shù)的含義:
 - (void)observeValueForKeyPath:(nullable NSString *)keyPath ofObject:(nullable id)object change:(nullable NSDictionary<NSString*, id> *)change context:(nullable void *)context;
  • 最后要移除觀察者:
- (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath;

KVO是怎么實(shí)現(xiàn)的?

當(dāng)某個(gè)類的對象第一次被觀察時(shí)喂很,系統(tǒng)就會在運(yùn)行期動(dòng)態(tài)地創(chuàng)建該類的一個(gè)派生類惜颇,在這個(gè)派生類中重寫基類中被觀察屬性的 setter 方法,在setter方法里使其具有通知機(jī)制少辣。因此凌摄,要想KVO生效,必須直接或間接的通過setter方法訪問屬性(KVC的setValue就是間接方式)漓帅。直接訪問成員變量KVO是不生效的锨亏。

同時(shí)派生類還重寫了 class 方法以“欺騙”外部調(diào)用者它就是起初的那個(gè)類。然后系統(tǒng)將這個(gè)對象的 isa 指針指向這個(gè)新誕生的派生類忙干,因此這個(gè)對象就成為該派生類的對象了器予,因而在該對象上對 setter 的調(diào)用就會調(diào)用重寫的 setter,從而激活鍵值通知機(jī)制捐迫。此外乾翔,派生類還重寫了 dealloc 方法來釋放資源。
重新的setter方法里到底干了什么施戴,而使其就有了通知機(jī)制呢末融?其實(shí)只是在setter方法里钧惧,給屬性賦值的前后分別調(diào)用了兩個(gè)方法

- (void)willChangeValueForKey:(NSString *)key;
- (void)didChangeValueForKey:(NSString *)key;
而- (void)didChangeValueForKey:(NSString *)key;會調(diào)用

- (void)observeValueForKeyPath:(nullable NSString *)keyPath ofObject:(nullable id)object change:(nullable NSDictionary<NSString*, id> *)change context:(nullable void *)context;

這就是KVO實(shí)現(xiàn)的基本原理了!
當(dāng)沒有存取方法而通過KVC的setValue修改屬性值時(shí)勾习,同樣的在運(yùn)行時(shí)也會在setValue:forKey方法里默認(rèn)調(diào)用上面?zhèn)z方法浓瞪。
其實(shí)我們也可以手動(dòng),顯式的調(diào)用這兩個(gè)方法巧婶,以使其具有通知機(jī)制乾颁。
下面用例子驗(yàn)證:

#import "ViewController.h"

@interface ViewController ()
{
    NSString            *_testStr;
}

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    // 給self的添加self觀察者,自己觀察自己的testStr成員變量
    [self addObserver:self forKeyPath:@"testStr" options:NSKeyValueObservingOptionNew context:nil];

    [self willChangeValueForKey:@"testStr"];
    _testStr = @"this is a test"; // 直接修改成員變量的值艺栈,但是顯式的英岭、手動(dòng)的調(diào)用上下倆方法,使其就有通知機(jī)制
    [self didChangeValueForKey:@"testStr"];
}


- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context
{
    if(object == self && [keyPath isEqualToString:@"testStr"])
    {
        NSLog(@"----new:%@----",change[@"new"]);
    }else
    {
        [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
    }
}


- (void)dealloc
{
    // 移除觀察者
    [self removeObserver:self forKeyPath:@"stuName"];
}

@end
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末湿右,一起剝皮案震驚了整個(gè)濱河市诅妹,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌毅人,老刑警劉巖吭狡,帶你破解...
    沈念sama閱讀 217,907評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異丈莺,居然都是意外死亡划煮,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,987評論 3 395
  • 文/潘曉璐 我一進(jìn)店門缔俄,熙熙樓的掌柜王于貴愁眉苦臉地迎上來弛秋,“玉大人,你說我怎么就攤上這事俐载⌒仿裕” “怎么了?”我有些...
    開封第一講書人閱讀 164,298評論 0 354
  • 文/不壞的土叔 我叫張陵遏佣,是天一觀的道長挖炬。 經(jīng)常有香客問我,道長贼急,這世上最難降的妖魔是什么茅茂? 我笑而不...
    開封第一講書人閱讀 58,586評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮太抓,結(jié)果婚禮上空闲,老公的妹妹穿的比我還像新娘。我一直安慰自己走敌,他們只是感情好碴倾,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,633評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般跌榔。 火紅的嫁衣襯著肌膚如雪异雁。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,488評論 1 302
  • 那天僧须,我揣著相機(jī)與錄音纲刀,去河邊找鬼。 笑死担平,一個(gè)胖子當(dāng)著我的面吹牛示绊,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播暂论,決...
    沈念sama閱讀 40,275評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼面褐,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了取胎?” 一聲冷哼從身側(cè)響起展哭,我...
    開封第一講書人閱讀 39,176評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎闻蛀,沒想到半個(gè)月后匪傍,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,619評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡循榆,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,819評論 3 336
  • 正文 我和宋清朗相戀三年析恢,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了墨坚。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片秧饮。...
    茶點(diǎn)故事閱讀 39,932評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖泽篮,靈堂內(nèi)的尸體忽然破棺而出盗尸,到底是詐尸還是另有隱情,我是刑警寧澤帽撑,帶...
    沈念sama閱讀 35,655評論 5 346
  • 正文 年R本政府宣布泼各,位于F島的核電站,受9級特大地震影響亏拉,放射性物質(zhì)發(fā)生泄漏扣蜻。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,265評論 3 329
  • 文/蒙蒙 一及塘、第九天 我趴在偏房一處隱蔽的房頂上張望莽使。 院中可真熱鬧,春花似錦笙僚、人聲如沸芳肌。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,871評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽亿笤。三九已至翎迁,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間净薛,已是汗流浹背汪榔。 一陣腳步聲響...
    開封第一講書人閱讀 32,994評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留肃拜,地道東北人揍异。 一個(gè)月前我還...
    沈念sama閱讀 48,095評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像爆班,于是被迫代替她去往敵國和親衷掷。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,884評論 2 354

推薦閱讀更多精彩內(nèi)容