**委託** 是一對一通訊機制:委託者持有符合特定**協定** 的受託者參考,發生特定事件時呼叫受託者的協定方法。關鍵三要素:
@required/@optional)。id <Protocol> delegate,觸發事件時呼叫。Wanted@protocol Wanted <NSObject>
@required
- (int)saveHerDad; // 回傳 0 失敗,1 成功
- (void)killTheBadGuy; // 內部實作細節
@end
Girl (Lucy)
@interface Girl : NSObject
@property (nonatomic, copy) NSString *name;
@property (nonatomic, assign) id <Wanted> delegate;
- (instancetype)initWithName:(NSString *)name withDelegate:(id<Wanted>)delegate;
- (void)helpHelp; // 觸發求救流程
@end
@implementation Girl
- (instancetype)initWithName:(NSString *)name withDelegate:(id<Wanted>)delegate {
self = [super init];
if (self) {
_name = name;
_delegate = delegate; // 弱引用,避免循環保留
}
return self;
}
- (void)helpHelp {
NSLog(@"%@: My dad was taken, can you save him?", _name);
NSLog(@"%@: OK, wait for good news!", _delegate);
// 模擬非同步:每 2 秒檢查一次救援進度
[NSTimer scheduledTimerWithTimeInterval:2 target:self
selector:@selector(checkRescue:) userInfo:@"Dad" repeats:YES];
}
- (void)checkRescue:(NSTimer *)timer {
if ([_delegate respondsToSelector:@selector(saveHerDad)]) {
int result = [_delegate saveHerDad];
if (result == 0) {
NSLog(@"%@: Still not saved... woo woo.", _name);
} else {
NSLog(@"%@: Thank you! Marry me~", _name);
[timer invalidate]; // 成功則停止計時器
}
}
}
@end
Cowboy (John Marston)
@interface Cowboy : NSObject
@property (nonatomic, copy) NSString *name;
@end
@implementation Cowboy
static int rescueStage = 0; // 模擬多階段救援
- (int)saveHerDad {
printf("\n");
rescueStage = [self killTheBadGuy];
if (rescueStage == 0) {
NSLog(@"%@: Too many bandits! I'll bring my posse!", _name);
rescueStage++;
return 0; // 第一次失敗
} else {
NSLog(@"%@ and crew: All bad guys down, here is your father.", _name);
return 1; // 成功
}
}
- (int)killTheBadGuy { return rescueStage; } // 內部狀態機
- (NSString *)description { return _name; } // 方便 NSLog 直接列印
@end
int main() {
@autoreleasepool {
Cowboy *john = [[Cowboy alloc] init];
john.name = @"John Marston";
Girl *lucy = [[Girl alloc] initWithName:@"Lucy" withDelegate:john];
[lucy helpHelp];
// 跑 RunLoop 6 秒讓計時器觸發數次
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:6]];
}
return 0;
}
Lucy: My dad was taken, can you save him?
John Marston: OK, wait for good news!
John Marston: Too many bandits! I'll bring my posse!
Lucy: Still not saved... woo woo.
John Marston and crew: All bad guys down, here is your father.
Lucy: Thank you! Marry me~
assign (ARC 下 weak):防止循環保留導致記憶體洩漏。respondsToSelector: 防護:受託者可能未實作 @optional 方法。NSObject:確保 respondsToSelector: 等方法可用。@implementation 內部,對外僅暴露協定介面。此範例以生動故事完整演示 Objective-C 委託模式的定義、串聯與執行流程。理解其核心——**協定定義介面、委託者觸發、受託者實作**——即可靈活應用於 UITableView/DataSource、網路層回呼、自訂視圖互動等經典場景。