在 iOS: MVC 中,我貼了張經典圖:
其中的Model向Controller通信的Noification&KVO為何物呢?
在功能上說,delegate、Notification以及KVO的功能類似,都是作用於OC中對象的消息通信。但三者的使用場景是不同的。簡單的說Delegate是一種回掉函數,更多的用在一對一的場合,可參考 iphone:delegate機制 ;Notification 用得較少,使用Notification Center,類似廣播方式,所以更適合一對多的通信;KVO,key-Value-Observing,觀察者模式,適用於偵聽另一對象的屬性的變化。
三者的詳細區別可以參考另一博文:http://mobile.51cto.com/iphone-386316.htm
Notification:
notification的使用十分簡單,直接看代碼:
//使用類方法獲取實例 NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; //增加2個消息監聽,消息名都為logInfo,一個在本對象中監聽,監聽方法GetInfo;一個在oneobj對象監聽,監聽方法oneObjHandleInfo。 [center addObserver:self selector:@selector(GetInfo:) name:@"logInfo" object:nil]; [center addObserver:oneobj selector:@selector(oneObjHandleInfo:) name:@"logInfo" object:nil]; //發送消息,消息名logInfo,傳遞數據為一個NSString [center postNotificationName:@"logInfo" object:@"00000"];
對應的2個接收方法:
//本對象中... -(void) GetInfo:(NSNotification *) notificaion{ //取得接受數據並打印 NSString *data = [notificaion object]; NSLog(@">> %@",data); } //OneObj對象中... -(void) oneObjHandleInfo:(NSNotification*) notification{ //取得接受數據並打印 NSString *data = [notification object]; NSLog(@">>OneOBJ %@",data); }
這樣就實現了post一個消息的時候,對應的2個監聽者都能收到消失並做出相關處理。最后要注意的是在不用的時候把對應的監聽給remove掉。
[center removeObserver:self name:@"logInfo" object:nil]; [center removeObserver:oneobj name:@"logInfo" object:nil];
KVO:
在看KVO之前,有必要先了解下KVC,即,Key-Value Coding 鍵值對編程。通過key-value可以方便的存取數據。
具體的操作簡單說就是:setValue:forKey: valueForKey:
//book Object //.h #import <Foundation/Foundation.h> @class Author; @interface Book : NSObject{ NSString *name; Author *author; float price; NSArray *relativeBooks; } @end //.m #import "Book.h" @implementation Book @end
Book *book = [[Book alloc] init]; [book setValue:@"iOS book" forKey:@"name"]; NSString *name = [book valueForKey:@"name"]; NSLog(@">> %@",name); Author *author = [[Author alloc] init]; [author setValue:@"Zhan" forKey:@"name"]; [book setValue:author forKey:@"author"]; NSString *authorName = [book valueForKeyPath:@"author.name"]; NSLog(@">> %@",authorName); [book setValue:@"100" forKey:@"price"]; NSLog(@">> %@",[book valueForKey:@"price"]); Book *book1 = [[Book alloc] init]; [book1 setValue:@"4" forKey:@"price"]; Book *book2 = [[Book alloc] init]; [book2 setValue:@"6" forKey:@"price"]; NSArray *books = [NSArray arrayWithObjects:book1,book2,nil]; [book setValue:books forKey:@"relativeBooks"]; NSLog(@">>%@",[book valueForKeyPath:@"relativeBooks.price"]);
更詳細的KVC介紹可以參考: http://marshal.easymorse.com/tech/objc-%E4%BD%BF%E7%94%A8kvc
KVO是基於kvc實現的,采取的是觀察者的模式:
book4=[[Book alloc] init]; //增加觀察者,為本類,keypath為book中的price對象,所以為price [book4 addObserver:self forKeyPath:@"price" options:NSKeyValueObservingOptionOld|NSKeyValueObservingOptionNew context:nil]; //修改值 [book4 setValue:@"4" forKey:@"price"];
//回掉方法 -(void) observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{ NSLog(@"cel back"); if([keyPath isEqual:@"price"]){ NSLog(@">>>>>>>price is changed"); NSLog(@"old price is %@",[change objectForKey:@"old"]); NSLog(@"new price is %@",[change objectForKey:@"new"]); } }
這樣便實現了當對象屬性改變時,做出相應反應。
更詳細KVO實現也可以參照:http://blog.csdn.net/yuquan0821/article/details/6646400
那KVC、KVO內部是如何實現的呢?
“一個對象在調用setValue的時候,(1)首先根據方法名找到運行方法的時候所需要的環境參數。(2)他會從自己isa指針結合環境參數,找到具體的方法實現的接口。(3)再直接查找得來的具體的方法實現。
因為KVC的實現機制,可以很容易看到某個KVC操作的Key,而后也很容易的跟觀察者注冊表中的Key進行匹對。假如訪問的Key是被觀察的Key,那么我們在內部就可以很容易的到觀察者注冊表中去找到觀察者對象,而后給他發送消息。”
詳細check:http://www.cocoadev.cn/Cocoadev/KVO-20100222-0627.asp
iOS中oc通信的通知和KVO大概就是這些了。