跳到主要内容

iOS 生命周期与 Swift Concurrency

🍎 iOS 生命周期管理是稳定性的关键。Swift Concurrency(async/await)带来了结构化并发和 Actor 模型。

UIViewController 生命周期

viewDidLoad → viewWillAppear → viewDidAppear

viewWillDisappear → viewDidDisappear → deinit

关键回调说明

回调时机常见操作
viewDidLoadView 层载完成,仅一次初始化 UI、加载数据
viewWillAppear每次显示前刷新数据、更新状态栏
viewDidAppear展示完成开始动画、起动计时
viewWillDisappear即将隐藏保存输入、取消网络
viewDidDisappear已隐藏停止动画、释放资源

App 生命周期(UIApplicationDelegate)

func application(_ app: UIApplication, didFinishLaunchingWithOptions...) -> Bool
func applicationWillResignActive(_ application: UIApplication) // 即将进入后台
func applicationDidEnterBackground(_ application: UIApplication) // 已进入后台
func applicationWillEnterForeground(_ application: UIApplication) // 将进入前台
func applicationDidBecomeActive(_ application: UIApplication) // 已激活

SwiftUI 生命周期

struct ContentView: View {
@State private var data: [Item] = []

var body: some View {
List(data) { item in ItemRow(item: item) }
.onAppear {
loadData() // 视图出现时
}
.onDisappear {
cleanup() // 视图消失时
}
.task { // 运行异步任务,视图消失自动取消
await fetchData()
}
}
}

Swift Concurrency

async/await 基础

// 声明异步函数
func fetchUser(id: Int) async throws -> User {
let url = URL(string: "https://api.example.com/users/\(id)")!
let (data, _) = try await URLSession.shared.data(from: url)
return try JSONDecoder().decode(User.self, from: data)
}

// 调用
Task {
do {
let user = try await fetchUser(id: 1)
await MainActor.run { updateUI(user) }
} catch {
print(error)
}
}

结构化并发

// async let 并行执行
async let user = fetchUser(id: 1)
async let posts = fetchPosts(userId: 1)
let (resolvedUser, resolvedPosts) = try await (user, posts)

// TaskGroup
let results = try await withThrowingTaskGroup(of: Item.self) { group in
for id in ids {
group.addTask { try await fetchItem(id: id) }
}
return try await group.reduce(into: []) { $0.append($1) }
}

Actor

// Actor 确保并发安全
actor DataCache {
private var cache: [String: Data] = [:]

func store(key: String, data: Data) {
cache[key] = data
}

func retrieve(key: String) -> Data? {
cache[key]
}
}

// @MainActor 确保在主线程执行
@MainActor
class ViewModel: ObservableObject {
@Published var items: [Item] = []

func loadItems() async {
items = await fetchItems() // 自动切换到主线程
}
}

常见误区

  • viewDidLoad 进行耐时网络请求,阴塞 UI 生成
  • 在非主线程直接更新 UI,应使用 @MainActorDispatchQueue.main
  • Task 创建的协程没有取消,导致视图销毁后仍在运行