Question 6
Task lifecycles in UIKit and SwiftUI
How do you tie the lifecycle of async tasks to a view (such as a SwiftUI view or a UIViewController) so you don't leak work or update deallocated UI?
Answer outline
In SwiftUI, prefer .task { } on the view. It creates work scoped to the view's lifetime that SwiftUI cancels when the view leaves the hierarchy, and .task(id:) restarts it when the id changes. Avoid orphan Task.detached calls from views.
In UIKit, store the Task handle on the view controller and call cancel() in viewWillDisappear and deinit. Capture [weak self] so the task doesn't keep the controller alive.
Work leaks when a detached task or a strong capture of self outlives the view controller. A stored Task that you cancel on disappear fixes most cases. After an await, assume the controller may already be gone, so guard the weak reference or check Task.isCancelled before touching UI.
Principles
- In SwiftUI use
.taskrather thanonAppear { Task { } }, because.taskauto-cancels when the view disappears andonAppeardoesn't. .task(id:)cancels the previous task and re-runs whenever the id changes, which suits selection-driven loads.- In UIKit store the handle and cancel in
viewWillDisappear, withdeinitas the safety net. - Capture
[weak self]in the task, because it may still be running after the view controller is gone.
struct ProfileView: View {
@StateObject private var model = ProfileModel()
let userId: String
var body: some View {
VStack {
// ...
}
.task(id: userId) {
await model.load(userId: userId)
}
}
}
final class FeedViewController: UIViewController {
private var loadTask: Task<Void, Never>?
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
loadTask?.cancel()
loadTask = Task { [weak self] in
// Strong self until load() returns, so cancel on disappear matters
guard let self else { return }
await self.viewModel.load()
}
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
loadTask?.cancel()
loadTask = nil
}
deinit { loadTask?.cancel() }
}



