CodeRoadMap
首页路线题库资源库文章社区
CodeRoadMap

程序员的学习成长路线图。内容免费开放,登录后可同步路线图与课时进度。

由 程序员柏风 独立维护 · 关于作者

学习

  • 路线图
  • 课程
  • 面试题
  • 文章
  • 我

更多

  • 资源
  • 社区
  • 关于作者
  • 内容说明

© 2026 CodeRoadMap

津ICP备2026012044号-1·津公网安备12011002026155号·coderoadmap@126.com
SwiftUI 开发入门/课时/并发与 async/await
RawBlame
课时目录12 节

SwiftUI 开发入门

  1. 01Swift 与 SwiftUI 概览
  2. 02基础语法与类型
  3. 03控制流
  4. 04函数与闭包
  5. 05结构体、类与协议
  6. 06SwiftUI 视图
  7. 07状态管理
  8. 08导航与生命周期
  9. 09并发与 async/await
  10. 10数据持久化
  11. 11MVVM 与架构
  12. 12综合练习

并发与 async/await

Task、Actor、SwiftUI 异步加载。

35 分钟

并发与 async/await

Swift 并发模型:async/await、Task、Actor 保证线程安全。对照 /roadmaps/swift-ui「并发」节点,网络加载与 UI 更新必须正确分离主线程与后台任务。

学习目标

  • 理解 @MainActor 与主线程 UI 更新规则
  • 用 Task、TaskGroup 执行异步工作
  • 掌握 Actor 隔离可变状态
  • 在 SwiftUI 中用 .task 与 async ViewModel 加载数据

核心概念

async/await 与 MainActor

struct Weather: Decodable {
    let city: String
    let temp: Double
    let condition: String
}

enum WeatherError: Error {
    case networkFailed
}

func fetchWeather(city: String) async throws -> Weather {
    try await Task.sleep(nanoseconds: 500_000_000)
    return Weather(city: city, temp: 22.5, condition: "晴")
}

@MainActor
final class WeatherViewModel: ObservableObject {
    @Published var weather: Weather?
    @Published var isLoading = false
    @Published var errorMessage: String?

    func load(city: String) async {
        isLoading = true
        errorMessage = nil
        do {
            weather = try await fetchWeather(city: city)
        } catch {
            errorMessage = "加载失败"
        }
        isLoading = false
    }
}

struct WeatherView: View {
    @StateObject private var viewModel = WeatherViewModel()
    @State private var city = "北京"

    var body: some View {
        VStack(spacing: 16) {
            TextField("城市", text: $city)
                .textFieldStyle(.roundedBorder)

            if viewModel.isLoading {
                ProgressView("加载中…")
            } else if let w = viewModel.weather {
                Text("\(w.city) \(w.temp, specifier: "%.1f")°C")
                Text(w.condition).foregroundStyle(.secondary)
            }

            Button("刷新") {
                Task { await viewModel.load(city: city) }
            }
        }
        .padding()
        .task(id: city) { await viewModel.load(city: city) }
    }
}

@MainActor 保证 @Published 变更在主线程;ViewModel 标注 @MainActor 是 SwiftUI 最佳实践。

Actor 与 TaskGroup

actor ImageCache {
    private var storage: [URL: Data] = [:]

    func data(for url: URL) -> Data? {
        storage[url]
    }

    func store(_ data: Data, for url: URL) {
        storage[url] = data
    }
}

func fetchMultiple(urls: [URL]) async -> [Data] {
    await withTaskGroup(of: Data?.self) { group in
        for url in urls {
            group.addTask {
                try? Data(contentsOf: url)
            }
        }
        var results: [Data] = []
        for await data in group {
            if let data { results.append(data) }
        }
        return results
    }
}

Actor 串行化内部可变状态,避免数据竞争;TaskGroup 并行执行子任务并收集结果。

与 React/SwiftUI 对照

Swift 并发ReactSwiftUI
async/awaitasync/awaitViewModel 方法
@MainActor—(单线程 DOM)UI 状态更新
Task { }useEffect 内 IIFE按钮触发
.taskuseEffect + cleanup视图生命周期
ActorWeb Worker(近似)线程安全缓存
TaskGroupPromise.all并行请求

React 18 的 useTransition 降低 UI 阻塞;Swift 用 Main Actor 隔离 UI,后台 Task 完成后 @MainActor 回写状态。

练习

  • 实现 @MainActor ViewModel,async 加载 mock 数据
  • 用 .task(id:) 监听搜索词变化并防抖请求
  • 编写 actor Counter 演示并发安全自增
  • 对比 React Promise.all 与 TaskGroup 并行加载

小结

async/await 简化异步 + MainActor 保护 UI + Actor 隔离共享状态。 下一课数据持久化。见 swift-ui-essentials。

加载本节练习…
← 上一课导航与生命周期下一课 →数据持久化