聊聊 KVO 與 KVC 吧

先聊聊 KVO 與 KVC 的區別吧:
KVO是指鍵-值-觀察者模式, 鍵值監聽, 監聽一個對象屬性值的改變。KVO是基于KVC的。
KVC 是指鍵-值編碼, 通過一個字符串的 key 來找到value , 是 value for key 方法, 直接或通過實例變量訪問的機制 。利用 KVC 可以隨意修改一個對象的屬性或者成員變量, 并且私有變量也可修改。

一. KVO

KVO是指鍵-值-觀察者(key-value-observe),
是一種使對象獲取其他對象的特定屬性變化的通知機制。
與NSNotification 不同的是。KVO 不需要通知中心對象。而是在對象屬性變化之后會直接通知觀察者。

KVO的步驟:

**1. 注冊觀察者 **
為了正確接收屬性的變化通知,觀察者對象必須先發一個消息給被觀察者對象

- (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(nullable void *)context;

/*
NSKeyValueObservingOptions 可選的是一個枚舉值。我們通常用到的是兩個
NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew
當屬性發生變化時。我們可以把舊值和新值傳遞給觀察者 
*/

**2.接收變化通知 **
應該注意的是如果只是使用成員變量改變值的話是不會觸發KVO的。要使用點語法,或者是KVC的方式改變值

// object 是被監聽對象
- (void)observeValueForKeyPath:(NSString *)keyPath
                      ofObject:(id)object
                        change:(NSDictionary<NSString *,id> *)change
                       context:(void *)context;

**3.移除觀察者身份 **
在不需要觀察時要進行移除

- (void)removeObserver:(NSObject *)observer
            forKeyPath:(NSString *)keyPath;

二.KVC

什么是KVC
KVC是指key-value-code,鍵-值編碼,是一種用于間接訪問對象屬性的機制。使用KVC可以直接修改對象屬性,即使是私有的也可以訪問。 如果是基本數據類型的應該封裝一下。

KVC的基本使用有下面幾點:
鍵值訪問
路徑訪問
取數組內的數據
一些簡單的運算
下面按照這幾點用法來介紹一下

// 為了方便以后操作,我們先簡單定義一下幾個類

// Person類
#import <Foundation/Foundation.h>
#import "Totoro.h"

@interface Person : NSObject

@property (nonatomic, copy) NSString *name;
@property (nonatomic, assign) NSUInteger age;
@property (nonatomic, strong) Totoro *Totoro;
@property (nonatomic, strong) NSArray *Totoros;

@end

// Totoro類
#import <Foundation/Foundation.h>

@interface Totoro : NSObject

@property (nonatomic, assign) NSUInteger weight;

@end

// 為了證明上面說的可以修改私有屬性,我們為 Totoro 添加一個私有的屬性
#import "Totoro.h"

@interface Totoro ()

@property (nonatomic, copy) NSString *name;

@end

@implementation Totoro

@end

基本設置完了之后,我們可以在Main函數里面進行一下操作

// 先創建一個人對象
Person *me = [[Person alloc] init];
Totoro *Totoro = [[Totoro alloc] init];
me.Totoro = Totoro; // 我養了一只龍貓

按照我們最為傳統的賦值方法我們要給人賦值一個name的話 我們通常會使用點語法進行賦值

// 本質上是調用了 [me setName:@"smile麗"];
me.name = @"smile麗"; // 這里相當于調用了setter方法

// 本質上是調用了 NSLog(@"%@", [me name]);
NSLog(@"%@", me.name); // 這里相當于調用getter方法

1> 鍵值訪問

那我們來看一下 使用KVC的方式應該如何去賦值.使用KVC, 會自動尋找成員變量(xxx),如果找不到,然后再去掉去尋找,如果再找不到,就會報錯。而不是去調用setter 和 getter 方法

// @() 對基本數據類型封裝成對象
 [me setValue:@(24) forKey:@"age"];
 NSLog(@"%@", [me valueForKey:@"age"]);

2> 路徑訪問

什么是路徑訪問,對于一個類來說,可能他的屬性是其他的類,如果要修改這里的屬性。我們需要先通過路徑來尋找到該屬性,然后再進行賦值.

[me setValue:@"大白" forKeyPath:@"totoro.name"]; // 注意這里的(.)只是路徑不是點語法
NSLog(@"%@", [me valueForKeyPath:@"totoro.name"]);

3> 取數組的數據

對于如果我們的數組里面存放的是對象,如果我們要獲取數組里面每個對象的屬性。這樣的話,最容易的方法就是遍歷數組。然后取出每個屬性進行添加到數組中。這時候我們也可以使用KVC快速解決這種問題.
為了測試,我給Person一個totoros的數組屬性,下面造一下數據.

NSMutableArray *totoros = [NSMutableArray array];
for (int i = 0; i < 4; i++) {
    Totoro *totoro = [[totoro alloc] init];
    NSString *name = [NSString stringWithFormat:@"大白_%d", i];
    [totoro setValue:name forKey:@"name"];
    NSUInteger weight = 3.8 + i;
    [totoro setValue:@(weight) forKey:@"weight"]; // 這個數據在第四點用到
    [totoros addObject:totoro];
}

我們如何實現上述的需求呢

使用 KVC回去屬性的數組

NSMutableArray *array = [totoros mutableArrayValueForKeyPath:@"name"];
NSLog(@"%@", array);
/*
 (
 "大白_0",
 "大白_1",
 "大白_2",
 "大白_3"
 )
*/

4> 一些簡單的運算
可以使用的關鍵字: 數量@count, 最大值@max, 最小值@min, 和@sum

me.totoros = totoros;
// 取到所有的相關屬性元素,進行計算, 由于方法返回的是 id, 所以要使用對象接收,我們可以使用 NSNumber, 而不是 int 之類的
NSLog(@"數量:%@", [p valueForKeyPath:@"totoros.@count"]);
NSLog(@"平均體重%@", [p valueForKeyPath:@"totoros.@avg.weight"]);
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,786評論 6 534
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,656評論 3 419
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,697評論 0 379
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,098評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,855評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,254評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,322評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,473評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,014評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,833評論 3 355
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,016評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,568評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,273評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,680評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,946評論 1 288
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,730評論 3 393
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,006評論 2 374

推薦閱讀更多精彩內容

  • 在編程中,最常見的就是程序的流程取決于你所使用的各種變量和屬性的值,根據變量和屬性的值確定后面運行的代碼,有時會檢...
    pro648閱讀 1,654評論 2 27
  • *面試心聲:其實這些題本人都沒怎么背,但是在上海 兩周半 面了大約10家 收到差不多3個offer,總結起來就是把...
    Dove_iOS閱讀 27,196評論 30 471
  • 最近發現之前看的東西沒一會就忘記了,所以寫來好一些,也建議大家吧學到了記錄下來這樣加深印象,也可以幫助到別人。首先...
    _技術支持閱讀 935評論 1 1
  • KVC/KVO 概念 KVC : 即 Key-Value-Coding,用于鍵值編碼。作為 cocoa 的一個標準...
    滿臉胡茬的小碼農閱讀 1,972評論 2 8
  • 1.KVC 關于 KVC 和 KVO ,我之前的總結文章有寫過,但是趨于表面,沒有探究其內部真正的實現原理和進階用...
    Liberalism閱讀 1,105評論 0 5