在 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大概就是這些了。