代理模式是 Cocoa 框架的核心設計範式,貫穿 UI 交互、網絡請求、數據源驅動等所有異步協作場景。本文從協議定義、注入機制、運行時流程、與 Java Listener/C++ 虛函數的對比五個維度,建立完整的 delegate 認知體系。
@protocol)。id 類型引用。// 協議定義 (簡化) @protocol UIActionSheetDelegate@optional - (void)actionSheet:(UIActionSheet*)sheet clickedButtonAtIndex:(NSInteger)idx; - (void)actionSheetCancel:(UIActionSheet*)sheet; - (void)willPresentActionSheet:(UIActionSheet*)sheet; - (void)didPresentActionSheet:(UIActionSheet*)sheet; - (void)actionSheet:(UIActionSheet*)sheet willDismissWithButtonIndex:(NSInteger)idx; - (void)actionSheet:(UIActionSheet*)sheet didDismissWithButtonIndex:(NSInteger)idx; @end // 初始化時注入代理 UIActionSheet *sheet = [[UIActionSheet alloc] initWithTitle:@"Title" delegate:self // self 遵守 UIActionSheetDelegate cancelButtonTitle:@"取消" destructiveButtonTitle:@"確定" otherButtonTitles:@"項目一", @"項目二", nil]; [sheet showInView:self.view];
@optional 方法無需全部實現,運行時以 respondsToSelector: 動態檢查。assign (MRC) / weak (ARC) 避免循環引用。otherButtonTitles 順序,取消按鈕固定為最後一個。// 1. 定義協議 @protocol ButtonClickDelegate- (void)onClick:(id)sender; @end // 2. 被委託者 @interface UIView : NSObject @property (nonatomic, weak) id clickDelegate; - (void)performClick; @end @implementation UIView - (instancetype)init { if ((self = [super init])) { _clickDelegate = self; // 默認自我代理 } return self; } - (void)onClick:(id)sender { NSLog(@"View 默認處理"); } - (void)performClick { [_clickDelegate onClick:self]; } @end // 3. 委託者/控制器 @interface ViewController : NSObject @property (nonatomic, strong) UIView *contentView; @end @implementation ViewController - (void)onClick:(id)sender { NSLog(@"Controller 處理點擊"); } @end // 4. 運行時切換 int main() { @autoreleasepool { UIView *view = [[UIView alloc] init]; [view performClick]; // 輸出: View 默認處理 ViewController *vc = [[ViewController alloc] init]; view.clickDelegate = vc; // 注入外部代理 [view performClick]; // 輸出: Controller 處理點擊 } }
| 概念 | Objective-C | Java (Android) | C# | C++ |
|---|---|---|---|---|
| 契約 | @protocol | interface | interface | 純虛類/Concept |
| 代理引用 | id | Listener 引用 | delegate 關鍵字 / event | std::function / 虛函數 |
| 注入 | 屬性賦值 | setOnClickListener | += 運算符 | 構造函數/Setter |
| 調用 | [delegate onClick:self] | listener.onClick(v) | delegate.Invoke() | callback() / virt_func() |
| 多播 | 需手動實現 (NotificationCenter) | 單播為主 | 事件原生支持多播 | signal/slot 或多播委託 |