KVC
KVC概述
KVC
即 Key-value coding
鍵值編碼,是指iOS的開發中,可以允許開發者通過Key
名直接訪問對象的屬性,或者給對象的屬性賦值。
KVC案例
@interface Person : NSObject@property (nonatomic,assign) int age;
@property (nonatomic,copy) NSString *name;@end
復制代碼
如以上代碼,我們創建了一個 Person
類,他有兩個屬性,分別是 age
和 name
。 然后我們將其實例化,并且賦予其姓名和年齡屬性:
Person *p1 =[Person new];
p1.name = @"Kobe";
p1.age = 30;
復制代碼
這是常規的賦值方式,那么KVC是如何賦值的呢?
[p1 setValue:@"Kobe" forKey:@"name"];
[p1 setValue:@"38" forKey:@"age"];
復制代碼
如以上代碼,通過KVC,我們可以直接使用鍵值對的方式對對象的屬性進行賦值。
同理,獲取屬性也可以使用鍵值對的方式:
[p1 valueForKey: @"name"];
[p1 valueForKey:@"age"];
復制代碼
這樣即可獲取對象的 name
和 age
屬性。
那么給我們再設置一個 Dog
類
@interface Dog : NSObject
@property (nonatomic,copy) NSString *name;
@end
復制代碼
給 Person
類增加一個 Dog
屬性
@property (nonatomic,strong) Dog *dog;
復制代碼
實例化 Dog
對象并初始化,然后賦值給 Person
對象
Dog *dog1 = [Dog new];
dog1.name = @"旺財";
p1.dog = dog1;
復制代碼
那么如何使用KVC給獲取 p1
的 dog
的 name
屬性呢? 只需要嵌套一層:
// 獲取
[[p1 valueForKey:@"dog"] valueForKey:@"name"];
// 設置
[[p1 valueForKey:@"dog"] setValue:@"狗狗" forKey:@"name"];
復制代碼
還有一種簡潔的方法就是使用以下方法
// 設置
[p1 setValue:@"狗狗" forKeyPath:@"dog.name"];
// 獲取
[p1 valueForKeyPath:@"dog.name"];
復制代碼
直接使用 "." 連接屬性即可。
KVO
KVO 即 Key-Value Observing
是基于 KVC 的一種觀察者模式,它可以通過 KVC 的方式對對象的屬性觀測,當 keyPath
的值變化時會發出通知。
KVO的實現方法
KVO的實現是以下三個步驟:
- 向通知中心注冊觀察
- 在某一時刻
keyPath
的值變化,通知中心向觀察者發送消息,調用方法。 - 重寫
dealloc
方法,注銷觀察。
KVO的案例
首先我們先創建一個類用于數值變化,這里就叫 KVOItem
類,給它添加一個 int
類型屬性 number
。
@interface KVOItem : NSObject
@property (nonatomic,assign) int number;
@end
復制代碼
然后創建并初始化對象,并為其添加觀察:
item = [KVOItem new];
item.number = 0;
[item addObserver:self forKeyPath:@"number" options:NSKeyValueObservingOptionOld|NSKeyValueObservingOptionNew context:@"KVOTEST"];
復制代碼
這里觀察 item
中 key
值為 number
的屬性。 注冊觀察后,需要實現觀察所調用的方法
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context{if (context == @"KVOTEST") {NSLog(@"change from %@ to %@",[change valueForKey:@"old"],[change valueForKey:@"new"]);}
}
復制代碼
然后我們使用一個 NSTimer
來重復更改 item
的 number
屬性。
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:3 repeats:YES block:^(NSTimer *timer){item.number++;}];[timer fire];
復制代碼
并且不要忘了在 dealloc
方法中注銷觀察:
-(void)dealloc{[item removeObserver:self forKeyPath:@"KVOTEST"];
}
復制代碼
運行后我們可以看到在控制臺打印以下消息:
change from 0 to 1
change from 1 to 2
change from 2 to 3
change from 3 to 4
復制代碼