KVC和KVO的學習
- KVC介紹
KVC的本質(zhì)就是鍵值編碼
定義:在對象創(chuàng)建完成之后,動態(tài)(牽扯到運行時)給對象的屬性賦值
KVC 即是指NSKeyValueCoding,一個非正式的Protocol,提供一種機制來間接訪問對象的屬性,而不是通過調(diào)用setter,getter方法訪問 - KVC的強大之處
<1> 訪問私有變量
一個類中的私有變量,不能直接通過Setter,Getter方法訪問,但是卻可以通過KVC來訪問
@interface Dog:NSObject{
@private
double height;
}
Dog *dog = [[Dog alloc]init];
[dog setValue:@12 forKey:@"height"];//給私有變量賦值
NSLog(@"dog's height is = %@",[dog valueForKey:@"height"]);//讀取私有變量的值 ```
實際用例
利用KVC的這個特性,我們可以訪問系統(tǒng)里的一些私有變量,例如在UIPageControl里面有兩個私有變量
UIImage *_currentPageImage;
UIImage *_pageImage;
我們通過KVC來進去讀取和賦值
UIPageControl *pageControl = [[UIPageControl alloc]init];
//設置值
[pageControl setValue:[UIImage imageNamed:@"XX"] forKeyPath:@"_currentPageImage"];
[pageControl setValue:[UIImage imageNamed:@"XX"] forKeyPath:@"_pageImage"];
//讀取值
UIImage *currentImage = [pageControl valueForKey:@"_currentPageImage"];
UIImage *pageImage = [pageControl valueForKey:@"_pageImage"];
UIPageControl *pageControl = [[UIPageControl alloc]init];
//設置值
[pageControl setValue:[UIImage imageNamed:@"XX"] forKeyPath:@"_currentPageImage"];
[pageControl setValue:[UIImage imageNamed:@"XX"] forKeyPath:@"_pageImage"];
//讀取值
UIImage *currentImage = [pageControl valueForKey:@"_currentPageImage"];
UIImage *pageImage = [pageControl valueForKey:@"_pageImage"];
使用KVC直接訪問NSArray或者NSSet的屬性值
NSArray *books= @[book1, book2, book3];
NSArray *names = [books valueForKeyPath:@"name"];
NSLog(@"%@", [books valueForKeyPath:@"@avg.price"]);//使用kvc直接打印出來書的平均價格
其中,book是一個書類,有一個屬性是name,一個屬性是price。
使用KVC將字典轉(zhuǎn)化成模型
// 定義一個字典
NSDictionary *dict = @{
@"name" : @"jack",
@"money" : @"20.7",
};
// 創(chuàng)建模型
Person *p = [[Person alloc] init];
// 字典轉(zhuǎn)模型
[p setValuesForKeysWithDictionary:dict];
NSLog(@"person's name is the %@",p.name);}
注意:
(1). key的值必須正確,如果拼寫錯誤,會出現(xiàn)異常
(2). 當key的值是沒有定義的,valueForUndefinedKey:這個方法會被調(diào)用,如果你自己寫了這個方法,key的值出錯就會調(diào)用到這里來
(3). 因為類key反復嵌套,所以有個keyPath的概念,keyPath就是用.號來把一個一個key鏈接起來,這樣就可以根據(jù)這個路徑訪問下去
(4). NSArray/NSSet等都支持KVC
KVO的本質(zhì)就是鍵值監(jiān)聽,他是基于KVC實現(xiàn)的關鍵技術之一,
定義:Key-Value Observing ,他提供一種機制,當指定的對象的屬性被修改后,則對象會接收到通知
KVO實現(xiàn)原理是當XXX類第一次被監(jiān)聽時,系統(tǒng)會再運行時期動態(tài)的創(chuàng)建一個繼承XXX的NSKVONOtifying_xxx類,在這個子類中,重寫基類中任何被觀察屬性的setter方法,而沒有被觀察的屬性則沒有重新生成setter方法,在setter方法中實現(xiàn)真正的通知機制
- (void)setAge:(int)age{
[self willChangeValueForKey:@“age”];
[super setAge:age];
[self didChangeValueForKey:@"age"];//這個方法負責調(diào)用
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context;
}
###KVO,delegate,NSNotification及block的區(qū)別
KVO就是cocoa框架實現(xiàn)的觀察者模式,一般同KVC搭配使用,通過KVO可以監(jiān)測一個值的變化,比如View的高度變化,是一對多的關系,一個值的變化會通知所有的觀察者
NSNotification是通知,也是一對多的使用場景,在某些情況下,KVO和NSNotification是一樣的,都是狀態(tài)變化之后告知對方。NSNotification的特點就是需要被觀察者先主動發(fā)出通知,然后觀察者注冊監(jiān)聽之后再來進行響應,比起KVO多了發(fā)送通知的一步,但是其優(yōu)點是監(jiān)聽不局限于屬性的變化,還可以對多種多樣的狀態(tài)變化進行監(jiān)聽,監(jiān)聽范圍廣,使用也靈活
delegate是代理,就是我不想做的事情交給別人做,比如狗需要吃飯,就通過delegate通知主人,主人就會做飯,盛飯這些操作,這些狗都不需要關心,只需要調(diào)用delegate(代理人)就可以了,由其他類完成所需要的操作,所以delegate是一對一的關系
block是delegate的另一種形式,是函數(shù)式編程的一種形式,使用場景和delegate一樣,相比delegate更靈活,實現(xiàn)上也更為直觀。
KVO一般的使用場景是數(shù)據(jù),需求是數(shù)據(jù)變化,比如股票價格變化,我們一般使用KVO(觀察者模式).
delegate一般的使用場景是行為,需求是需要別人來幫我做一件事情,比如買賣股票,我們一般使用delegate
NSNOtification一般是進行全局通知,比如利好消息一出,通知大家去買入,delegate是強關聯(lián),就是委托和代理雙方互相知道,你委托別人買股票你就需要知道經(jīng)紀人,但是經(jīng)紀人也要知道自己的顧客。Notifation是弱關聯(lián),利好消息發(fā)出,你不需要知道是誰發(fā)的也可以做出相應的反應,同理,發(fā)消息的人也不需要知道有誰接收,也能發(fā)出消息
##參考文獻
--[http://www.mamicode.com/info-detail-515516.html]
--[http://blog.csdn.net/woaifen3344/article/details/48054729] 標哥的技術博客