在iOS開發(fā)中,通知(Notification)傍妒、鍵值編碼(KVC)幔摸、鍵值觀察(KVO)和代理(Delegate)是四種常見的設(shè)計(jì)模式和通信機(jī)制。它們各自有獨(dú)特的特點(diǎn)和適用場景颤练,同時(shí)也有一定的聯(lián)系既忆。以下將從它們的區(qū)別與聯(lián)系出發(fā),并結(jié)合OC語言示例進(jìn)行說明嗦玖。
1. 通知(NSNotification)
特點(diǎn):
一對多通信:通知允許一個(gè)對象向多個(gè)接收者發(fā)送消息患雇,適用于解耦的場景。
全局通知:通過NSNotificationCenter管理宇挫,可以在整個(gè)應(yīng)用范圍內(nèi)發(fā)送和接收通知苛吱。
靈活性:可以攜帶自定義信息,但無法直接返回結(jié)果器瘪。
適用場景:
控制器之間傳遞事件信息翠储。
視圖模型層與控制器層之間的通信绘雁。
示例代碼:
// 發(fā)送通知
NSNotification *notification = [NSNotification notificationWithName:@"MyNotification" object:self];
[[NSNotificationCenter defaultCenter] postNotification:notification];
// 接收通知
[[NSNotificationCenter defaultCenter] addObserver:self
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? selector:@selector handleNotification:]
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? name:@"MyNotification"
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? queue:nil];
- (void)handleNotification:(NSNotification *)notification {
? ? NSLog(@"Received notification");
}
2. 鍵值編碼(KVC)
特點(diǎn):
間接訪問對象屬性:通過字符串鍵名訪問對象的屬性,無需調(diào)用getter或setter方法彰亥。
動(dòng)態(tài)性:支持動(dòng)態(tài)修改屬性值咧七,但編譯時(shí)無法檢查錯(cuò)誤。
效率較低:相比直接調(diào)用方法任斋,性能稍低继阻。
適用場景:
動(dòng)態(tài)屬性操作,如數(shù)據(jù)綁定废酷。
簡化代碼瘟檩,減少重復(fù)的getter/setter方法。
示例代碼:
// 設(shè)置屬性值
?self.myProperty = @"Hello"; // 直接調(diào)用
?[self setValue:@"Hello" forKey:@"myProperty"]; // KVC方式
// 獲取屬性值
NSString *value = self.myProperty; // 直接調(diào)用
NSString *kvcValue = [self valueForKey:@"myProperty"]; // KVC方式
3. 鍵值觀察(KVO)
特點(diǎn):
觀察者模式:允許對象監(jiān)聽其他對象的屬性變化澈蟆,并在變化時(shí)觸發(fā)回調(diào)墨辛。
動(dòng)態(tài)性:通過運(yùn)行時(shí)機(jī)制實(shí)現(xiàn),無需修改被觀察對象的代碼趴俘。
靈活性:支持單對多關(guān)系睹簇,但需要手動(dòng)注冊和注銷觀察者。
適用場景:
視圖模型層與控制器層之間的通信寥闪。
實(shí)現(xiàn)MVC或MVVM架構(gòu)中的數(shù)據(jù)綁定太惠。
示例代碼:
// 注冊觀察者
[self addObserver:self forKeyPath:@"myProperty"
?? ? ? ? ? changeHandler:^(id obj, NSKeyValueChange change, NSKeyValueChangeReason reason, NSKeyValueChangeContext *context) {
?? ? ? ? ? ? ? NSLog(@"Property changed");
?? ? ? ? ? }];
// 觀察屬性變化
- (void)observeValueForKeyPath:(NSString *)keyPath
?? ? ? ? ? ? ? ? ? ? ? ofObject:(id)object
?? ? ? ? ? ? ? ? ? ? ? ? change:(NSDictionary *)change
? ? ? ? ? ? ? ? ? ? context:(void *)context {
? ? NSLog(@"Received change for keyPath: %@", keyPath);
}
// 移除觀察者
[self removeObserver:self forKeyPath:@"myProperty"];
4. 代理(Delegate)
特點(diǎn):
一對一通信:通常用于兩個(gè)對象之間的協(xié)作,調(diào)用方通過協(xié)議定義方法疲憋,被調(diào)用方實(shí)現(xiàn)這些方法凿渊。
嚴(yán)格耦合:代理模式要求調(diào)用方和被調(diào)用方之間有明確的接口約定。
靈活性:可以返回值缚柳,便于控制流程埃脏。
適用場景:
視圖控制器與模型之間的交互。
實(shí)現(xiàn)復(fù)雜的業(yè)務(wù)邏輯秋忙。
示例代碼:
// 定義協(xié)議
@protocol MyDelegate <NSObject>
- (void)actionCompleted;
@end
// 實(shí)現(xiàn)協(xié)議
@interface MyViewController : UIViewController <MyDelegate>
@end
// 使用代理
- (void)doSomething {
? ? MyViewController *vc = [[MyViewController alloc] init];
? ? vc.delegate = self;
? ? [vc performTask];
}
- (void)actionCompleted {
? ? NSLog(@"Action completed");
}
區(qū)別與聯(lián)系
區(qū)別:
通知:一對多通信彩掐,全局通知,適用于解耦場景灰追。
KVC/KVO:鍵值操作佩谷,KVC用于動(dòng)態(tài)訪問屬性,KVO用于監(jiān)聽屬性變化监嗜。
代理:一對一通信谐檀,嚴(yán)格耦合,適用于協(xié)作場景裁奇。
聯(lián)系:
通知與KVO:都可以用于對象間的通信桐猬,但通知更適用于全局通信,而KVO更適合細(xì)粒度的屬性監(jiān)聽刽肠。
代理與KVO:代理模式可以替代KVO的部分功能溃肪,尤其是在需要返回值或控制流程的場景中免胃。
總結(jié)
在實(shí)際開發(fā)中,選擇合適的設(shè)計(jì)模式和通信機(jī)制需要根據(jù)具體需求來決定惫撰。例如羔沙,在需要解耦的場景中優(yōu)先考慮通知;在需要細(xì)粒度監(jiān)聽屬性變化時(shí)選擇KVO厨钻;在需要嚴(yán)格控制流程時(shí)使用代理扼雏。通過合理結(jié)合這些模式,可以提高代碼的可讀性和可維護(hù)性夯膀。