溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

iOS開發(fā)中KVC、KVO簡介

發(fā)布時間:2020-03-28 00:21:29 來源:網(wǎng)絡 閱讀:354 作者:張立達 欄目:移動開發(fā)

在iOS開發(fā)中,KVC和KVO是經(jīng)常被用到的。可以使用KVC對對象的屬性賦值和取得對象的屬性值,可以使用KVO監(jiān)聽對象屬性值的變化。簡單介紹一下KVC和KVO。

一:鍵值編碼(KVC)

KVC,全稱 Key Value Coding(鍵值編碼),是OC 語言的一個特性,使用KVC,可以對對象的屬性進行動態(tài)讀寫。

KVC的操作方法由 NSKeyValueCoding協(xié)議提供,而NSObject已經(jīng)實現(xiàn)了這個協(xié)議,因此OC中的幾乎所有對象都可以使用KVC操作。常用的KVC操作方法有:

(1)設置屬性值

  setValue:value forKey:key (用于簡單路徑,也就是直接屬性)

  setValue: value forKeyPath:key (用于復雜路徑,也就是間接屬性)

(2)獲取屬性值

  valueForKey: key  (用于獲取簡單路徑的屬性值)

  valueForKeyPath: key (用于獲取復雜路徑的屬性值)

通過代碼來看KVC的具體使用:

兩個類分別是Dog類和Person類

Dog.h

iOS開發(fā)中KVC、KVO簡介

1 #import <Foundation/Foundation.h>2 3 @interface Dog : NSObject4 5 @property (nonatomic, copy) NSString *name;6 7 @end

iOS開發(fā)中KVC、KVO簡介

Dog.m

1 #import "Dog.h"2 3 @implementation Dog4 5 @end

Person.h

iOS開發(fā)中KVC、KVO簡介

 1 #import <Foundation/Foundation.h> 2  3 @class Dog; 4  5 @interface Person : NSObject 6  7 @property (nonatomic, copy) NSString *name; 8 @property (nonatomic, copy) NSString *sex; 9 10 @property (nonatomic, strong) Dog *dog;11 12 @end

iOS開發(fā)中KVC、KVO簡介

Person.m

1 #import "Person.h"2 3 @implementation Person4 5 @end

KVC的使用:

iOS開發(fā)中KVC、KVO簡介

 1 Person *person = [[Person alloc] init]; 2     //kvc  設置值 3     [person setValue:@"Jim" forKey:@"name"]; 4     [person setValue:@"boy" forKey:@"sex"]; 5      6     //kvc 獲得值 7     NSLog(@"name = %@  sex = %@",[person valueForKey:@"name"],[person valueForKey:@"sex"]); 8      9     Dog *dog = [[Dog alloc] init];10     person.dog = dog;11     //kvc  設置復雜路徑值12     [person setValue:@"Teddy" forKeyPath:@"dog.name"];13     //kvc  獲得復雜路徑值14     NSLog(@"dog name = %@",[person valueForKeyPath:@"dog.name"]);

iOS開發(fā)中KVC、KVO簡介

可以看到,KVC使用對應的函數(shù)即可設置值、獲得值。那么,KVC是如何查找一個屬性進行讀取呢?KVC遵循下面的規(guī)則,假設要對name屬性進行讀?。?/p>

(1)設置屬性:優(yōu)先考慮setName方法;如果沒有,則搜索成員變量_name;如果沒找到,則搜索成員變量name;如果還沒有找到,則調(diào)用 setValue: forUndefineKey: 方法。

(2)讀取屬性:優(yōu)先考慮getName方法;如果沒有,則搜索成員變量_name;如果沒找到,則搜索成員變量name;如果還沒有找到,則調(diào)用 valueForUndefineKey: 方法。

二:KVC中 setValuesForKeysWithDictionary: 的使用

KVC中有一個非常重要的方法: setValuesForKeysWithDictionary:dict ,該方法可以將一個字典映射到一個對象,省去了給對象一一賦值的步驟。

使用 setValuesForKeysWithDictionary:dict 的一個例子:

student.h

 

iOS開發(fā)中KVC、KVO簡介

 1 #import <Foundation/Foundation.h> 2  3 @interface Student : NSObject 4  5 /** 6  *  學號 7  */ 8 @property (nonatomic, copy) NSString *num; 9 /**10  *  姓名11  */12 @property (nonatomic, copy) NSString *name;13 /**14  *  身高15  */16 @property (nonatomic, assign) float height;17 18 /**19  *  初始化的兩個方法20  *21  */22 - (instancetype)initWithDict:(NSDictionary *)dict;23 + (instancetype)stuWithDict:(NSDictionary *)dict;24 25 27 28 @end

iOS開發(fā)中KVC、KVO簡介

 

student.m

iOS開發(fā)中KVC、KVO簡介

 - (instancetype)initWithDict:(NSDictionary *     (self =          + (instancetype)stuWithDict:(NSDictionary *

iOS開發(fā)中KVC、KVO簡介

用一個字典初始化對象

iOS開發(fā)中KVC、KVO簡介

 1 - (void)initStudent 2 { 3     NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys: 4     @"Tom",@"name", 5     @"110",@"num", 6     @"170.0",@"height", 7     nil]; 8     Student *stu = [[Student alloc] initWithDict:dict]; 9     NSLog(@"name = %@ num = %@ height = %f",stu.name,stu.num,stu.height);10 }

iOS開發(fā)中KVC、KVO簡介

setValuesForKeyWithDictionary:dict  的原理

  實際上,setValuesForKeyWithDictionary:dict 方法就是遍歷dict,對dict 中的每個鍵值調(diào)用 setValue: forKey: 方法??梢杂孟旅娴姆椒MsetValuesForKeyWithDictionary:dict:

iOS開發(fā)中KVC、KVO簡介

1 - (void) setProperty:(NSDictionary *)dict2 {3     for(NSString *key in [dict allKeys])4     {5         NSString *value = [dict objectForKey:key];6         [self setValue:value forKey:key];7     }8 }

iOS開發(fā)中KVC、KVO簡介

調(diào)用時:

iOS開發(fā)中KVC、KVO簡介

1 - (instancetype)initWithDict:(NSDictionary *)dict{2     if(self = [super init]){3         //[self setValuesForKeysWithDictionary:dict];4         [self setProperty:dict];5     }6     return self;7 }

iOS開發(fā)中KVC、KVO簡介

和setValuesForKeyWithDictionary:dict 功能是一樣的。

使用setValuesForKeyWithDictionary:dict一個需要注意的地方

當字典中有某個值,而對象沒有相應的屬性時,會發(fā)生崩潰。比如,新的字典如下:

iOS開發(fā)中KVC、KVO簡介

 1 - (void)initStudent 2 { 3     NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys: 4     @"Tom",@"name", 5     @"110",@"num", 6     @"170.0",@"height", 7     @"boy",@"sex",nil]; 8     Student *stu = [[Student alloc] initWithDict:dict]; 9     NSLog(@"name = %@ num = %@ height = %f",stu.name,stu.num,stu.height);10 }

iOS開發(fā)中KVC、KVO簡介

字典中有 sex屬性,但是Studeng對象中沒有這個屬性,此時會發(fā)生崩潰。解決方法:

實現(xiàn) setValue:  forUndefineKey:  方法,在該方法中處理出現(xiàn)沒有屬性的情況。

student.h中添加代碼:

1 - (void)setValue:(id)value forUndefinedKey:(NSString *)key;

student.m中添加代碼:

1 - (void)setValue:(id)value forUndefinedKey:(NSString *)key2 {3     4 }

當出現(xiàn)沒有屬性的情況時,就會調(diào)用 setValue: forUndefineKey: 方法。因為該方法沒做處理,所以這種情況不做處理,不會發(fā)生崩潰。需要注意的是:setValue: forUndefineKey: 方法用途很廣泛,比如說字典中某個key值 為id,但是在OC中id 是關鍵字,這種情況也可以在 setValue: forUndefineKey: 方法中處理。

三:鍵值監(jiān)聽(KVO)

KVO全稱 Key Value Observing。使用KVO可以實現(xiàn)視圖組件和數(shù)據(jù)模型的分離,視圖作為監(jiān)聽器,當模型的屬性值發(fā)生變化后,監(jiān)聽器可以做相應的處理。KVO的方法由NSKeyValueObserving協(xié)議提供,同樣NSObject已經(jīng)實現(xiàn)了該協(xié)議,因此幾乎所有的對象都可以使用KVO。

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

注冊制定路徑的監(jiān)聽器: addObserver:  forKeyPath: option: context:

刪除制定路徑的監(jiān)聽器:removeObserver: forKeyPath:

觸發(fā)監(jiān)聽時的方法:observeValueForKeyPath: ofObject: change: context: 

一個KVO的例子:

有兩個類: Dog類和People類

Dog.h

 

iOS開發(fā)中KVC、KVO簡介

1 #import <Foundation/Foundation.h>2 3 @interface Dog : NSObject4 5 @property (nonatomic, copy) NSString *name;6 7 @end

iOS開發(fā)中KVC、KVO簡介

 

Dog.m

1 #import "Dog.h"2 3 @implementation Dog4 5 @end

People.h

iOS開發(fā)中KVC、KVO簡介

 1 #import <Foundation/Foundation.h> 2  3 @class Dog; 4  5 @interface People : NSObject 6  7 @property (nonatomic , copy) NSString *name; 8 @property (nonatomic , strong) Dog *dog; 9 10 @end

iOS開發(fā)中KVC、KVO簡介

People.m

iOS開發(fā)中KVC、KVO簡介

 1 #import "People.h" 2 #import "Dog.h" 3  4 @implementation People 5  6 /** 7  *  初始化時增加對dog的監(jiān)聽 8  * 9  */10 - (void)setDog:(Dog *)dog11 {12     _dog = dog;13     [self.dog addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew context:nil];14 }15 /**16  *  重寫observeValueForKeyPath方法17  */18 - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context19 {20     if([keyPath isEqualToString:@"name"]){21         NSLog(@"newName = %@",[change objectForKey:@"new"]);22     }23 }24 25 - (void)dealloc26 {27     //移除監(jiān)聽28     [self.dog removeObserver:self forKeyPath:@"name"];29 }30 31 @end

iOS開發(fā)中KVC、KVO簡介

測試KVO函數(shù):

iOS開發(fā)中KVC、KVO簡介

 1 - (void)testKVO 2 { 3     People *people = [[People alloc] init]; 4     people.name = @"Tom"; 5     Dog *dog = [[Dog alloc] init]; 6     dog.name = @"Teddy"; 7     people.dog = dog; 8      9     //執(zhí)行到這一步后,會觸發(fā)監(jiān)聽器的函數(shù)(observeValueForKeyPath)10     dog.name = @"testChange";11 }

iOS開發(fā)中KVC、KVO簡介

在代碼中,當修改dog 的name屬性時,就會觸發(fā)監(jiān)聽方法,也就是 

observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context 方法。


向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內(nèi)容。

AI