[iOS]KVO的相關知識

KVO,即Key-Value Observing,是 Objective-C 對觀察者模式(Observer Pattern)的一種實現(xiàn)烤蜕。也是 Cocoa Binding 的基礎堕担。當被觀察對象的某個屬性發(fā)生更改時翻斟,觀察者對象會獲得通知吮廉。
KVO的通知方式一般分為兩種,一種是** 自動通知 ** 畸肆,另一種是** 手動通知 宦芦,系統(tǒng)默認的是 自動通知 **。

KVO的實現(xiàn)步驟

首先我們要有一個類轴脐,在這篇文章的例子中调卑,我們來對這個類的屬性進行觀察。

類的實現(xiàn)如下:

.h 文件
#import <Foundation/Foundation.h>

@interface Person : NSObject

@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *gender;

@end
.m 文件
#import "Person.h"

@implementation Person

@end

KVO的實現(xiàn)一般有以下三步

1. 添加觀察大咱,并指定被觀察的屬性

我們在程序啟動時為Person類的實例對象添加觀察者恬涧,即當前控制器。為了一會解釋手動實現(xiàn)碴巾,我們把name和gender屬性都設置為被觀察的屬性溯捆。且觀察的是這兩個屬性的新值。

    Person *person = [[Person alloc] init];
    [person addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew context:nil];
    [person addObserver:self forKeyPath:@"gender" options:NSKeyValueObservingOptionNew context:nil];
    self.person = person;
2. 實現(xiàn)觀察方法

KVO觀察模式在被觀察屬性發(fā)生變化時厦瓢,會自動調(diào)用下面的方法提揍,我們要在方法里實現(xiàn)一些邏輯。

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context
{
    if ([keyPath isEqualToString:@"name"]) {
        NSLog(@"new name = %@", [change objectForKey:NSKeyValueChangeNewKey]);
    } else if ([keyPath isEqualToString:@"gender"]) {
        NSLog(@"new gender = %@", [change objectForKey:NSKeyValueChangeNewKey]);
    }
}
3. 移除觀察者

KVO會持有觀察者煮仇,所以在必要的時候劳跃,我們要移除觀察者。如果不移除浙垫,可能會造成訪問僵尸對象的情況刨仑,比如劉爽同學當時為一個單利變量添加了一個控制器觀察者,當這個控制器被pop掉后夹姥,單利中的值發(fā)生了改變杉武,結(jié)果在再次發(fā)出通知時,這個控制器變量不存在佃声,造成了訪問僵尸對象艺智,引起了奔潰。所以我們要移除觀察者圾亏。
移除觀察者一般是在觀察者的dealloc方法里完成的十拣。

- (void)dealloc
{
    [self.person removeObserver:self forKeyPath:@"name"];
    [self.person removeObserver:self forKeyPath:@"gender"];
}

自動通知的實現(xiàn)

現(xiàn)在封拧,我們就要進行被觀察屬性的修改了,看看自動通知是怎么工作的夭问。

    person.name = @"Alan Walker";
    person.gender = @"male";
    
    person.name = @"DJ Earworm";
    person.gender = @"male";

控制臺上打印

1.png

可見泽西,在KVO的自動通知中,只要是給被觀察對象賦值缰趋,無論該值是新值還是舊值捧杉,都會發(fā)出通知。

手動通知的實現(xiàn)

要實現(xiàn)手動通知秘血,我們需要對Person模型進行一些修改味抖。
在Person中添加** + (BOOL)automaticallyNotifiesObserversForKey:(NSString *)key; ** 方法

+ (BOOL)automaticallyNotifiesObserversForKey:(NSString *)key
{
    if ([key isEqualToString:@"name"]) {
        return NO;
    } else {
        return [super automaticallyNotifiesObserversForKey:key];
    }
}

這樣,我們就關閉了name屬性的自動通知灰粮。

1. 如果想要實現(xiàn)被觀察屬性在被賦的值與原來相同時仔涩,不進行通知,可以重寫name的setter方法
- (void)setName:(NSString *)name
{
    if (self.name != name) {
        [self willChangeValueForKey:@"name"];
        _name = name;
        [self didChangeValueForKey:@"name"];
    }
}

運行如下代碼

    person.name = @"Alan Walker";
    person.gender = @"male";
    
    person.name = @"DJ Earworm";
    person.gender = @"male";
    
    person.name = @"DJ Earworm";
    person.gender = @"male";

打印結(jié)果如下

2.png
2. 我們還可以按照自己的意愿讓通知啟動粘舟。

撤銷重寫setter方法熔脂,執(zhí)行如下代碼

    person.name = @"Alan Walker";
    person.gender = @"male";
    
    [person willChangeValueForKey:@"name"];
    person.name = @"DJ Earworm";
    [person didChangeValueForKey:@"name"];
    person.gender = @"male";

打印結(jié)果如下

3.png
由此可見,手動實現(xiàn)通知以下兩個方法比較重要柑肴。
- (void)willChangeValueForKey:(NSString *)key;
- (void)didChangeValueForKey:(NSString *)key;
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末霞揉,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子晰骑,更是在濱河造成了極大的恐慌适秩,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,376評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件些侍,死亡現(xiàn)場離奇詭異隶症,居然都是意外死亡,警方通過查閱死者的電腦和手機岗宣,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,126評論 2 385
  • 文/潘曉璐 我一進店門蚂会,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人耗式,你說我怎么就攤上這事胁住。” “怎么了刊咳?”我有些...
    開封第一講書人閱讀 156,966評論 0 347
  • 文/不壞的土叔 我叫張陵彪见,是天一觀的道長。 經(jīng)常有香客問我娱挨,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,432評論 1 283
  • 正文 為了忘掉前任酵镜,我火速辦了婚禮,結(jié)果婚禮上淮韭,老公的妹妹穿的比我還像新娘。我一直安慰自己靠粪,他們只是感情好蜡吧,可當我...
    茶點故事閱讀 65,519評論 6 385
  • 文/花漫 我一把揭開白布占键。 她就那樣靜靜地躺著,像睡著了一般畔乙。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上啸澡,一...
    開封第一講書人閱讀 49,792評論 1 290
  • 那天氮帐,我揣著相機與錄音嗅虏,去河邊找鬼。 笑死上沐,一個胖子當著我的面吹牛皮服,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播参咙,決...
    沈念sama閱讀 38,933評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼龄广,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了蕴侧?” 一聲冷哼從身側(cè)響起择同,我...
    開封第一講書人閱讀 37,701評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎净宵,沒想到半個月后敲才,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,143評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡择葡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,488評論 2 327
  • 正文 我和宋清朗相戀三年紧武,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片敏储。...
    茶點故事閱讀 38,626評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡阻星,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出已添,到底是詐尸還是另有隱情妥箕,我是刑警寧澤滥酥,帶...
    沈念sama閱讀 34,292評論 4 329
  • 正文 年R本政府宣布,位于F島的核電站矾踱,受9級特大地震影響恨狈,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜呛讲,卻給世界環(huán)境...
    茶點故事閱讀 39,896評論 3 313
  • 文/蒙蒙 一禾怠、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧贝搁,春花似錦吗氏、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,742評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至膀哲,卻和暖如春往产,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背某宪。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工仿村, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人兴喂。 一個月前我還...
    沈念sama閱讀 46,324評論 2 360
  • 正文 我出身青樓蔼囊,卻偏偏與公主長得像,于是被迫代替她去往敵國和親衣迷。 傳聞我的和親對象是個殘疾皇子畏鼓,可洞房花燭夜當晚...
    茶點故事閱讀 43,494評論 2 348

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

  • 本文結(jié)構(gòu)如下: Why? (為什么要用KVO) What? (KVO是什么) How? ( KVO怎么用) Mo...
    等開會閱讀 1,641評論 1 21
  • 本文由我們團隊的 糾結(jié)倫 童鞋撰寫。 文章結(jié)構(gòu)如下: Why? (為什么要用KVO) What? (KVO是什么...
    知識小集閱讀 7,409評論 7 105
  • 在編程中壶谒,最常見的就是程序的流程取決于你所使用的各種變量和屬性的值云矫,根據(jù)變量和屬性的值確定后面運行的代碼泼差,有時會檢...
    pro648閱讀 1,634評論 2 27
  • *面試心聲:其實這些題本人都沒怎么背,但是在上海 兩周半 面了大約10家 收到差不多3個offer,總結(jié)起來就是把...
    Dove_iOS閱讀 27,131評論 30 470
  • 海倫.凱勒的那篇《假如給我三天光明》是我年少時讀過的最美的一篇文字堆缘。文字中普碎,那段對自然的描述是那么美。
    平馨燕月閱讀 250評論 0 0