Как отменить долгосрочную задачу в ViewModel?
Это простой тест, но не простой. HomeView показывает TestView в виде листа, TestView скрывает почти все действия (без .task, onReceive...) в TestViewModel, TestViewModel определяет ориентацию устройства и показывает ее в TestView. при отклонении TestView остановите обнаружение.
Работает почти нормально, но при отклонении TestView печать («TestViewModel deinit.») не происходит, и обнаружение все еще работает.
Я думаю, что у Task есть ссылка на TestViewModel, из-за чего TestViewModel не может быть выпущен. Но как исправить?
ОК, следующий вопрос: как отменить задачу в TestViewModel (не в TestView) при отклонении TestView?
Любое предложение?
struct HomeView: View {
@State var showTestView = false
var body: some View {
Button("Show Test View") {
showTestView = true
}.sheet(isPresented: $showTestView) {
TestView()
}
}
}
struct TestView: View {
@StateObject private var vm = TestViewModel()
@Environment(\.dismiss) var dismiss
var body: some View {
VStack {
Text("isPortrait = \(vm.isPortrait.description)")
Button("Dismiss") {
dismiss()
}
}
.onDisappear {
print("TestView onDisappear.")
}
}
}
@MainActor
class TestViewModel: ObservableObject {
@Published var isPortrait = false
init() {
print("TestViewModel init.")
setup()
}
deinit {
print("TestViewModel deinit.")
}
func setup() {
Task {
await observeNotification()
}
}
private func observeNotification() async {
let sequence = NotificationCenter.default.notifications(named: UIDevice.orientationDidChangeNotification)
.map { _ in await UIDevice.current.orientation }
for await value in sequence {
print("orientationDidChangeNotification changed, orientation = \(value).")
isPortrait = value == .portrait
}
}
}