🙆♀️
【Swift】MainActor で隔離されたクラスの deinit を MainActor で実行する
MainActor で隔離されたクラスの deinit の前にisolatedをつけることで、 deinit を MainActor で実行させることができます。
isolated deinit { ... }
サンプル
struct ContentView: View {
@State private var isShowingFirstView = false
var body: some View {
VStack {
if isShowingFirstView == true {
FirstView()
}
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.overlay(alignment: .bottom) {
Button("Action") {
isShowingFirstView.toggle()
}
}
}
}
struct FirstView: View {
@State private var vm = FirstViewModel()
var body: some View {
Text("This is SecondView.")
.onAppear(perform: vm.onAppear)
}
}
@MainActor
final class FirstViewModel: ObservableObject {
@Published private(set) var task: Task<Void, Never>? = nil
/// メインアクターで実行されるのでこれでOK
///
isolated deinit {
task?.cancel()
}
// deinit {
// Task { @MainActor [weak self] in
// self?.task?.cancel
// }
// }
func onAppear() {
self.task = Task {
await asyncAction()
}
}
}
func asyncAction() async {
for i in 0..<100 {
do {
try await Task.sleep(for: .seconds(0.5))
print(i)
continue
} catch is CancellationError {
print("cancell")
} catch {
print(error)
}
break
}
}
Discussion