Swift 6.1 `withTaskGroup` & `withThrowingTaskGroup` 新语法导读

为什么需要 TaskGroup?

在 Swift 并发里,当你想:

  • 同时发起 N 个异步任务(如批量下载图片)
  • 等全部完成再汇总结果
  • 支持中途取消、错误传播

手动 Task { } 会显得碎片化且难以管理。

withTaskGroup / withThrowingTaskGroup 提供官方"任务组"抽象:

  1. 统一并发上限(线程池复用)
  2. 自动生命周期管理,无内存泄漏
  3. 支持结构化取消与错误聚合

Swift 6.1 的新语法亮点

版本 声明方式 是否必填子任务返回类型
≤ Swift 6.0 withTaskGroup(of: Int.self) ✅ 必须显式 of: Type.self
Swift 6.1 withTaskGroup { group in ... } ❌ 编译器自动推断

→ 去掉 of: 后,代码更短、重构更安心;复杂元组/struct 类型不再写两遍。

最小可运行示例:类型推断实战

  1. 简单数据并行
swift 复制代码
func fetchNumbers() async -> [Int] {
    await withTaskGroup { group in          // ← 不再需要 of: Int.self
        for i in 1...3 {
            group.addTask {                 // 返回 Int
                return i * 2
            }
        }

        var results = [Int]()
        for await value in group {
            results.append(value)
        }
        return results.sorted()
    }
}

// 使用
Task {
    let nums = await fetchNumbers()
    print(nums)   // [2, 4, 6]
}
  1. 复杂类型同样受益
swift 复制代码
struct ImageInfo { let url: URL, size: Int, checksum: UInt32 }

func batchDownload(_ urls: [URL]) async -> [ImageInfo] {
    do  {
        let infos = try await withThrowingTaskGroup { group in          // 自动推断 ImageInfo
            for url in urls {
                group.addTask {
                    let (data, _) = try await URLSession.shared.data(from: url)
                    return ImageInfo(
                        url: url,
                        size: data.count,
                        checksum: 2
                    )
                }
            }
            
            var infos = [ImageInfo]()
            for try await info in group {
                infos.append(info)
            }
            return infos
        }
        return infos
    } catch {
        print(error.localizedDescription)
    }
    return []
}

→ 若返回类型日后增加字段,无需改动 withTaskGroup 声明。

ThrowingTaskGroup:允许子任务抛出错误

  1. 基础示例(Swift 6.1 同样省 of:
swift 复制代码
func fetchUserInfo(ids: [String]) async throws -> [User] {
    try await withThrowingTaskGroup { group in   // 推断 String & User
        for id in ids {
            group.addTask {
                return try await API.user(id: id)  // 可能抛出
            }
        }

        var users = [User]()
        for try await user in group {              // 注意 try
            users.append(user)
        }
        return users
    }
}
  1. 错误传播规则
  • 任一子任务 throw → 整个组立即 throw(默认)
  • 想收集所有成功 + 单独处理失败 → 用 group.addTaskUnlessCancelled + do catch 内部吞错
swift 复制代码
for try await user in group {
    // 这里 throw 会**中断**后续任务
}

→ 需要"全部完成再统一处理"请参考 group.next() 手动迭代。

与 Swift 6 并发隔离的兼容

TaskGroup 的 addTask 继承调用者的隔离域:

swift 复制代码
@MainActor
class VM {
    func loadImages() async {
        await withTaskGroup { group in          // 主线程创建
            for url in urls {
                group.addTask {                 // 子任务**脱离**主线程
                    let data = try await URLSession.shared.data(from: url).0
                    return UIImage(data: data)!
                }
            }
            // 汇总时可回到主线程
            for await img in group {
                self.images.append(img)
            }
        }
    }
}

→ 网络下载在全局执行器,汇总后 images 回主线程,安全。

六、常见坑 & 最佳实践

陷阱 说明 修复
忘记 for await导致永远挂起 组内任务完成但结果未被消费 务必用 for awaitwhile let value = await group.next()
捕获 self造成循环引用 addTask { self.view.reload() } 使用 [weak self]或先把数据拉出来
想"无论成败都收集" 默认 for try await一遇 throw 就中断 内部 do catch手动 resume成功/失败数组
需要限制并发数量 withTaskGroup会全开 使用 AsyncSequence+ AsyncChannel或信号量

一句话总结

"批量并发用 Group,Swift 6.1 起别再写 of:。"

记住口诀:"普通组用 withTaskGroup,会抛错就 withThrowingTaskGroup;结果靠 for await 扫,错误用 try 收。"

去掉类型标注后,代码更短、重构更安心;让编译器多干活,你少写两行!

相关推荐
tiantian_cool14 小时前
Claude Code 四大核心技能使用指南
ios
冰淇淋真好吃18 小时前
iOS实现 WKWebView 长截图的优雅方案
ios
njsgcs19 小时前
Swift playground 网页刷新切换随机页面的网页查看器WebKit
swift
前端不太难1 天前
Flutter / RN / iOS,在长期维护下的性能差异本质
flutter·ios
搜狐技术产品小编20232 天前
精通 UITableViewDiffableDataSource——从入门到重构的现代 iOS 列表开发指南
ios·重构
tangweiguo030519872 天前
SwiftUI 状态管理完全指南:从 @State 到 @EnvironmentObject
ios
Digitally2 天前
如何轻松地将文件从 PC 传输到 iPhone
ios·iphone
iosTiov2 天前
当IPA遇见信任:解密ios生态中“签名”的真正力量
ios·团队开发·苹果签名·稳定
游戏开发爱好者82 天前
如何使用 AppUploader 提交上传 iOS 应用
android·ios·小程序·https·uni-app·iphone·webview
和沐阳学逆向2 天前
iOS 18 越狱教程:palera1n + 巨魔安装全流程
ios·巨魔商店·ios越狱·ios18越狱