2013年11月5日 星期二

Design Pattern - Observer Pattern

難得有看得懂得, 可以嘴砲一下

引用蘋果Observer Pattern介紹
The Observer design pattern defines a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.

Observer Pattern在Cocoa中有兩種實作方式
Notifications & Key-Value Observing


  • Notifications 
寫到一半發現以前有寫過, 只是不知道這是Design Pattern的一種, 直接把舊文章修改一下貼上, 少寫很多字

參考文章
類似 Observer Pattern 的 NSNotificationCenter
Delegates Vs. Notifications in iPhoneOS

NotificationCenter可以分為 "建立通知", "發送通知" ,"移除通知"

先來看建立通知
- (void)addObserver:(id)observer selector:(SEL)aSelector name:(NSString *)aName object:(id)anObject;
observer: 要在哪個class下實作這通知, 通常都是self, 也就是當下的class
aSelector: 發送通知後要執行的method的名稱
name: 為你的Notification命名個名稱吧
anObject: 可以指定只對某個object啟動Notification, 可以設nil就無條件通知

來寫個兩種作為後續說明用 , 以及一個post後要執行的自定mySelect方法
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(mySelect:) name:@"Notification" object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(mySelect:) name:@"Notification" object:self.lbl];
- (void)mySelect:(NSNotification *)notification {
 NSLog(@"%@",notification);
 NSLog(@"%@",[notification object]);
 NSLog(@"%@",[notification userInfo]);
}

發送通知有三個方法可以做, 拿最長的來說明
- (void)postNotificationName:(NSString *)aName object:(id)anObject userInfo:(NSDictionary *)aUserInfo;
aName: 會呼叫當時建立對應名稱的Notification
object: 同樣也是對應到在建立時候給的物件
aUserInfo: 傳遞自定參數給要執行的selector, 不需要就給nil

說明一些post情況
[[NSNotificationCenter defaultCenter] postNotificationName:@"Notification" object:self.lbl userInfo:@{@"Key2":@"Value2"}];
當這段程式執行後會去執行mySelector方法,而mySelector會被執行"兩次"
一次是跑addObserver的 name:@"Notification" object:nil 的selector
另一次是跑addObserver的 name:@"Notification" object:self.lbl 的selector
(add與post兩邊的self.lbl是相同物件)

[[NSNotificationCenter defaultCenter] postNotificationName:@"Notification" object:nil userInfo:@{@"Key2":@"Value2"}];;
當這段程式執行後會去執行mySelector方法,而mySelector會被執行"ㄧ次"
只有跑 addObserver的 name:@"Notification" object:nil 的selector

[[NSNotificationCenter defaultCenter] postNotificationName:@"Notification" object:self userInfo:nil];
當這段程式執行後會去執行mySelector方法,而mySelector會被執行"ㄧ次"
只有跑 addObserver 的 name:@"Notification" object:nil 這段的selecotr
此處的 object:self 是另外一個class, 也就是不同的物件

[[NSNotificationCenter defaultCenter] postNotificationName:@"nono" object:nil];
這段不會跑selector, 找不到對應的addObserver Name

移除通知不講了, 跟發送通知給的參數一樣道理, 可以寫在dealloc中, 當Class被移除順便移除通知
值得一提的是
[[NSNotificationCenter defaultCenter] removeObserver:self name:@"Notification" object:nil];
這會同時移除
[[NSNotificationCenter defaultCenter] removeObserver:self name:@"Notification" object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:@"Notification" object:self.lbl];
這兩個observer


[[NSNotificationCenter defaultCenter] removeObserver:self name:@"Notification" object:self.lbl];
只會單獨移除
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(mySelect:) name:@"Notification" object:self.lbl];

  • Key-Value Observing
相較於Notification需要post來觸發selector
Key-Value Observing可以觀察一個Object property的變化而自動呼叫method 用法還蠻簡單的, 一樣先看建立觀察的方法

- (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context;
observer: 跟notification用法一樣
forKeyPath: 要觀察receiver的property名稱, 用String去表示
options: 對此observer的一些操作,  詳情看蘋果文件

沒有留言:

張貼留言