首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

iOS 方法返回值延遲不阻塞主線程:使用 Block 回調 + dispatch_after 實現異步返回

     編輯:程式設計綜合問答

需求

方法 getValue 需延遲返回 CGFloat,但不阻塞調用線程(主線程)。

錯誤嘗試

-(CGFloat)getValue {
    // 無法在同步方法中實現非阻塞延遲返回
    return floatValue; 
}

同步方法必須立即返回,無法「暫停」函數執行。

正確模式:異步回調

Block 回調 + dispatch_after

- (void)asyncGetValueWithCompletion:(void (^)(CGFloat value))completion {
    dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)); // 2秒延遲
    dispatch_after(popTime, dispatch_get_main_queue(), ^{
        CGFloat result = [self computeValue]; // 耗時計算或網絡請求
        if (completion) completion(result);
    });
}

// 調用
[self asyncGetValueWithCompletion:^(CGFloat value) {
    // 主線程回調,更新 UI
    self.label.text = [NSString stringWithFormat:@"%.2f", value];
}];

進階:Promise/Future 模式 (第三方庫)

使用 PromiseKit、Bolts 或 RxSwift 鏈式異步:

// PromiseKit
- (PMKPromise *)fetchValue {
    return [PMKPromise promiseWithResolver:^(PMKResolver resolve, PMKRejecter reject) {
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 2*NSEC_PER_SEC), dispatch_get_main_queue(), ^{
            resolve(@([self computeValue]));
        });
    }];
}

// 調用
[self fetchValue].then(^(NSNumber *value) {
    self.label.text = [NSString stringWithFormat:@"%.2f", value.floatValue];
});

避坑指南

  • 絕不在主線程 sleep/wait:[NSThread sleepForTimeInterval:]、semaphore_wait 會凍結 UI,導致 Watchdog 崩潰 (0x8badf00d)。
  • 回調執行隊列:網絡請求回調通常在背景隊列,更新 UI 必須 dispatch_async(dispatch_get_main_queue(), ...)。
  • 循環引用:Block 中捕獲 self 需用 __weak typeof(self) weakSelf = self;。

同步轉異步重構清單

  1. 方法返回類型改為 void
  2. 添加 completion:(void(^)(ResultType))block 參數
  3. 內部異步操作完成後調用 block(result)
  4. 調用處改為回調寫法

「延遲返回不阻塞」本質是同步轉異步,Block 回調是 Objective-C 基礎模式,Swift 推薦 async/await 或 Combine。

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