第十章:现代化的救赎 —— Block 与 GCD

10.1 Block:闭包的方括号版本

在很久以前,OC 想要回调,只能靠 Delegate。 为了回传一个状态,你得写协议、设代理、实现方法……太累了。 后来,Apple 引入了 Blocks^)。

它的语法可以说是 OC 中最反人类的设计之一(著名的 fuckingblocksyntax.com 就是为此而生): returnType (^blockName)(parameterTypes) = ^returnType(parameters) {...};

但是,它让代码可以在原地执行回调。

[manager fetchWeathersWithCompletion:^(NSArray *weathers, NSError *error) {
    // 收到数据,直接在这里处理
    NSLog(@"Fetched: %@", weathers);
}];

这极大地简化了异步编程的逻辑。需要注意的是 循环引用(Retain Cycle):在 Block 里用 self,一定要先 __weak typeof(self) weakSelf = self;

10.2 GCD:把线程扔进队列

与 Blocks 一起诞生的,是 Grand Central Dispatch (GCD)。 在 GCD 之前,我们用 NSThreadNSOperation。 GCD 告诉我们:忘掉线程吧。你只需要关心队列(Queue)。

  • 串行队列 (Serial Queue): 一个接一个做。
  • 并发队列 (Concurrent Queue): 大家一起做。
  • 主队列 (Main Queue): 专门负责更新 UI 的(UI 只能在主线程更新)。
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    // 1. 在后台干脏活累活(下载图片)
    UIImage *img = [self downloadImage];
    
    dispatch_async(dispatch_get_main_queue(), ^{
        // 2. 回到主线程更新 UI
        self.imageView.image = img;
    });
});

这套 dispatch_async 的模板代码,是每一个 OC 程序员的肌肉记忆。 虽然 Swift 如今有了 async/await,但 GCD 依然是底层最坚实的基石。

使用 Hugo 构建
主题 StackJimmy 设计