iOS 生命周期与 Swift Concurrency
🍎 iOS 生命周期管理是稳定性的关键。Swift Concurrency(async/await)带来了结构化并发和 Actor 模型。
UIViewController 生命周期
viewDidLoad → viewWillAppear → viewDidAppear
↓
viewWillDisappear → viewDidDisappear → deinit
关键回调说明
| 回调 | 时机 | 常见操作 |
|---|---|---|
viewDidLoad | View 层载完成,仅一次 | 初始化 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,应使用
@MainActor或DispatchQueue.main -
Task创建的协程没有取消,导致视图销毁后仍在运行