Swift多线程方案-Concurrency

简介

Swift Concurrency(async/await)是从 Swift 5.5 开始引入的一套并发编程模型,用来替代传统的回调(callback)、闭包嵌套(callback hell)、以及部分 GCD 使用场景,让异步代码写起来像同步代码一样清晰。

async / await

  • async:标记函数是 异步函数
  • await:表示 等待异步结果

本质:await 会"挂起当前任务",但不会阻塞线程

示例

swift 复制代码
func fetchUser() async -> String {
    return "Tom"
}

func loadData() async {
    let user = await fetchUser()
    print(user)
}

async throws

支持错误处理(替代 callback 的 error)

swift 复制代码
enum NetworkError: Error {
    case failed
}

func fetchData() async throws -> String {
    throw NetworkError.failed
}

func load() async {
    do {
        let result = try await fetchData()
        print(result)
    } catch {
        print("error: \(error)")
    }
}

Task

Task 是并发执行的基本单位,类似 GCD 的 block,也是一个对象。

  • 普通 Task
scss 复制代码
Task {
    let data = await fetchUser()
    print(data)
}
ini 复制代码
let task = Task {
    ...
}
  • Detached Task(独立线程)
scss 复制代码
Task.detached {
    await doSomething()
}

区别:

Task:继承当前 Actor / 优先级 / 上下文

detached:完全独立(慎用)

async let

并发执行

场景:多个接口同时请求

swift 复制代码
func loadData() async {
    async let user = fetchUser()
    async let posts = fetchPosts()
    
    let result = await (user, posts)
    print(result)
}

TaskGroup

任务组

场景:批量请求 / 并发处理列表

csharp 复制代码
func fetchAll() async {
    await withTaskGroup(of: String.self) { group in
        for i in 1...3 {
            group.addTask {
                return "Task \(i)"
            }
        }
        
        for await result in group {
            print(result)
        }
    }
}

Actor

线程安全方案

用于解决数据竞争问题(替代锁)

swift 复制代码
actor Counter {
    private var value = 0
    
    func increment() {
        value += 1
    }
    
    func getValue() -> Int {
        return value
    }
}
scss 复制代码
let counter = Counter()

Task {
    await counter.increment()
    let v = await counter.getValue()
    print(v)
}

Actor = 自动串行队列 + 数据隔离

对比

方案 问题
NSLock 易死锁
DispatchQueue 需要手动管理
Actor 天然安全

实战应用场景

  • 网络请求
csharp 复制代码
func fetchUser() async -> User { ... }
func fetchPosts() async -> [Post] { ... }

func load() async {
    let user = await fetchUser()
    let posts = await fetchPosts()
}

------对比旧方案

arduino 复制代码
fetchUser { result in
    fetchPosts { posts in
        // 嵌套地狱
    }
}
  • 多个接口并发请求

多个请求任务并行执行,等待异步结果

csharp 复制代码
func loadPage() async {
    async let banner = fetchBanner()
    async let list = fetchList()
    async let profile = fetchProfile()
    
    let (b, l, p) = await (banner, list, profile)
}
  • 主线程更新UI
swift 复制代码
func loadData() {
    Task {
        let data = await fetchData()
        
        await MainActor.run {
            self.label.text = data
        }
    }
}

或 使用@MainActor

swift 复制代码
@MainActor
func updateUI() {
    label.text = "Hello"
}
  • 取消任务
ini 复制代码
let task = Task {
    let data = await fetchData()
}

task.cancel()
  • 图片加载
swift 复制代码
func downloadImage(url: URL) async throws -> UIImage {
    let (data, _) = try await URLSession.shared.data(from: url)
    return UIImage(data: data)!
}
ini 复制代码
let task = Task {
    let image = try await downloadImage(url: url)
    cell.imageView.image = image
}

注意:需要处理 cell 复用问题(取消任务)-》 避免图片错位

csharp 复制代码
override func prepareForReuse() {
    task?.cancel()
}
  • 顺序依赖
csharp 复制代码
func process() async {
    let token = await login()
    let data = await fetchData(token: token)
    let result = await parse(data)
}

对比

方案 特点
GCD 底层强,但难维护
Operation 可控但复杂
async/await 简洁 + 可读性强

本质: • GCD:你管理线程 • async/await:系统帮你调度

总结

Swift Concurrency 本质就是:

用"同步写法"写"异步代码",并且保证线程安全

相关推荐
itmigrate2 小时前
前端项目里,Object.is 并不是 === 的平替
前端
小大宇3 小时前
Vue知识点6-computed计算属性
前端·javascript·vue.js
程序员海军4 小时前
尤雨溪 : Vue 4 已经在规划中了!
前端·javascript·vue.js
2601_949970694 小时前
HumanizeDuration 跨端三方库仓颉适配全流程
前端·javascript·flutter
风骏时光牛马6 小时前
后端服务接口开发与性能优化
前端
kyriewen6 小时前
我让 4 个 AI 互相 review 代码,最温柔的那个下手最狠
前端·程序员·ai编程
计算机魔术师6 小时前
493家公司白砸AI钱?Apollo这组数据戳破了幻觉
前端
IT_陈寒6 小时前
Java静态变量初始化坑得我头皮发麻
前端·人工智能·后端
柳杉7 小时前
用 Codex 完成智慧高速 3D 可视化大屏,从 18 张行业设计稿到可交互的运行监测中心
前端·ai编程·数据可视化
review445437 小时前
拿到 codex 第一步
前端·agent·vibecoding