首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C >> 關於C

Objective-C 委託模式完整範例:牛仔救父記

     編輯:關於C

委託模式核心概念

**委託** 是一對一通訊機制:委託者持有符合特定**協定** 的受託者參考,發生特定事件時呼叫受託者的協定方法。關鍵三要素:

  1. 協定:定義方法清單(@required/@optional)。
  2. 委託者:持有 id <Protocol> delegate,觸發事件時呼叫。
  3. 受託者:遵循協定並實作方法,接收回呼。

故事場景:Lucy 委託 John Marston 救父

1. 協定 Wanted

@protocol Wanted <NSObject>
@required
- (int)saveHerDad;      // 回傳 0 失敗,1 成功
- (void)killTheBadGuy;  // 內部實作細節
@end

2. 委託者 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

3. 受託者 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

4. 主程式串聯


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~

關鍵最佳實踐

  1. delegate 屬性用 assign (ARC 下 weak):防止循環保留導致記憶體洩漏。
  2. 呼叫前用 respondsToSelector: 防護:受託者可能未實作 @optional 方法。
  3. 協定繼承 NSObject:確保 respondsToSelector: 等方法可用。
  4. 私有實作隱藏:受託者將協定方法放在 @implementation 內部,對外僅暴露協定介面。
  5. 一對多改用通知中心或 KVO:委託嚴格一對一,多對多請勿強行套用。

現代替代方案

  • Block 回呼:輕量、就地定義,適合單一非同步操作。
  • Promise/Future (PromiseKit 等):鏈式非同步、錯誤傳播更優雅。
  • Combine / RxSwift:響應式串流,適合複雜事件流。

結語

此範例以生動故事完整演示 Objective-C 委託模式的定義、串聯與執行流程。理解其核心——**協定定義介面、委託者觸發、受託者實作**——即可靈活應用於 UITableView/DataSource、網路層回呼、自訂視圖互動等經典場景。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved