iOS開發——實用篇&KVO與KVC詳解

來源:互聯網
上載者:User

標籤:

KVO與KVC詳解

由於ObjC主要基於Smalltalk進行設計,因此它有很多類似於Ruby、Python的動態特性,例如動態類型、動態載入、動態綁定等。今天我們著重介紹ObjC中的索引值編碼(KVC)、索引值監聽(KVO)特性:

  1. 索引值編碼KVC
  2. 索引值監聽KVO
索引值編碼KVC

我們知道在C#中可以通過反射讀寫一個對象的屬性,有時候這種方式特別方便,因為你可以利用字串的方式去動態控制一個對象。其實由於ObjC的語言特性,你根部不必進行任何操作就可以進行屬性的動態讀寫,這種方式就是Key Value Coding(簡稱KVC)。

KVC的操作方法由NSKeyValueCoding協議提供,而NSObject就實現了這個協議,也就是說ObjC中幾乎所有的對象都支援KVC操作,常用的KVC操作方法如下:

  • 動態設定: setValue:屬性值 forKey:屬性名稱(用於簡單路徑)、setValue:屬性值 forKeyPath:屬性路徑(用於複合路徑,例如Person有一個Account類型的屬性,那麼person.account就是一個複合屬性) 
  • 動態讀取: valueForKey:屬性名稱 valueForKeyPath:屬性名稱(用於複合路徑)
索引值監聽KVO

我們知道在WPF、Silverlight中都有一種雙向繫結機制,如果資料模型修改了之後會立即反映到UI視圖上,類似的還有如今比較流行的基於MVVM設計模式的前端架構,例如Knockout.js。其實在ObjC中原生就支援這種機制,它叫做Key Value Observing(簡稱KVO)。KVO其實是一種觀察者模式,利用它可以很容易實現視圖組件和資料模型的分離,當資料模型的屬性值改變之後作為監聽器的視圖組件就會被激發,激發時就會回調監聽器自身。在ObjC中要實現KVO則必須實現NSKeyValueObServing協議,不過幸運的是NSObject已經實現了該協議,因此幾乎所有的ObjC對象都可以使用KVO。

在ObjC中使用KVO操作常用的方法如下:

  • 註冊指定Key路徑的監聽器: addObserver: forKeyPath: options:  context:
  • 刪除指定Key路徑的監聽器: removeObserver: forKeyPathremoveObserver: forKeyPath: context:
  • 回調監聽: observeValueForKeyPath: ofObject: change: context:

KVO的使用步驟也比較簡單:

  1. 通過addObserver: forKeyPath: options: context:為被監聽對象(它通常是資料模型)註冊監聽器 
  2. 重寫監聽器的observeValueForKeyPath: ofObject: change: context:方法

/*********************************KVC/KVO*******************************************/

KVC

kvc在實際開發中使用最多的地方一般有兩個

  • 字典轉模型:但是這個有一個局限性,如果他的屬性也是一個模型的時候不能使用這個方法,或者不能一一對應的時候
  • 通過屬性鍵設定對應屬性的值

字典轉模型:

 1 #pragma mark 簡單字典轉模型 2         NSDictionary *dict = @{ 3                                @"name"  : @"jack", 4                                @"money" : @"20.7", 5                                }; 6      7         [p setValuesForKeysWithDictionary:dict]; 8         NSLog(@"name = %@, money = %f", p.name, p.money); 9     10 #pragma mark 複雜模型11     NSDictionary *dict = @{12                            @"name"  : @"jack",13                            @"money" : @"20.7",14                            @"dog" : @{15                                    @"name" : @"wangcai",16                                    @"price" : @"10.8"17                                    },18                            @"books" : @[19                                    @{20                                        @"name" : @"5分鐘突破iOS開發",21                                        @"price" : @"19.8"22                                        },23                                    @{24                                        @"name" : @"3分鐘突破iOS開發",25                                        @"price" : @"24.8"26                                        },27                                    @{28                                        @"name" : @"1分鐘突破iOS開發",29                                        @"price" : @"29.8"30                                        }31                                    ]32                            };33     [p setValuesForKeysWithDictionary:dict];34     NSLog(@"%@", p);35 }

 

設定屬性的值:

 1 #pragma mark 單個值 2         p.name = @"lnj"; 3         p.money = 99.8; 4      5         [p setValue:@"lnj" forKey:@"name"]; 6         [p setValue:@(99.8) forKey:@"money"]; 7         NSLog(@"name = %@, money = %f", p.name, p.money); 8      9 #pragma mark 多層賦值10     11         p.dog = [XMGDog new];12         p.dog.name = @"wangcai";13         p.dog.price = 998;14     15         [p.dog setValue:@"wangcai" forKey:@"name"];16         [p.dog setValue:@(998) forKey:@"price"];17     18         [p setValue:@"wangcai" forKeyPath:@"dog.name"];19         [p setValue:@(998) forKeyPath:@"dog.price"];20         NSLog(@"name = %@, price = %f", p.dog.name, p.dog.price);21     22 #pragma mark 私人屬性23     24         [p setValue:@"lnj" forKeyPath:@"_name"];25         [p setValue:@(30) forKeyPath:@"_age"];26     27         NSLog(@"name = %@", p.name);28         [p say];

 

 

KVO

1:建立一個對象

 1 iCocos *stu = [[iCocos alloc] init]; 2  

2:註冊指定Key路徑的監聽器,並且修改相應的屬性

1 [stu addObserver:self forKeyPath:@"score" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];2     3     stu.score = 90;4     5     stu.score = 100;

3:刪除指定Key路徑的監聽器

1 #warning 注意只有調用set方法修改才能監聽到 2 內部實現原理是: 系統會自動給我們產生一個子類, 然後重寫子類的set方法, 在set方法中通知監聽3     stu->_score = 250;4     [stu removeObserver:self forKeyPath:@"score"];

 

4:回調監聽

1 - (void)observeValueForKeyPath:(nullable NSString *)keyPath ofObject:(nullable id)object change:(nullable NSDictionary *)change context:(nullable void *)context2 {3     NSLog(@"keyPath = %@, obj = %@, change = %@, context = %@", keyPath, object, change, context);4 }

 

KVO內部實現機制:

 系統會自動給我們產生一個子類, 然後重寫子類的set方法, 在set方法中通知監聽

iOS開發——實用篇&KVO與KVC詳解

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.