视图消失时如何使用组合框架取消初始化 ViewModel
How to deinit ViewModel with combine framework when views disappears
我在 viewModels 中使用 Combine 来更新视图。但是,如果我将 AnyCancellable 对象存储到一组 AnyCancellable 中,则永远不会调用 deinit 方法。我使用 deinit 来取消所有可取消对象。
struct View1: View {
@ObservedObject var viewModel:ViewTextModel = ViewTextModel()
@Injected var appActions:AppActions
var body: some View {
VStack {
Text(self.viewModel.viewText)
Button(action: {
self.appActions.goToView2()
}) {
Text("Go to view \(self.viewModel.viewText)")
}
}
}
}
class ViewTextModel: ObservableObject {
@Published var viewText: String
private var cancellables = Set<AnyCancellable>()
init(state:AppState) {
// initial state
viewText = "view \(state.view)"
// updated state
state.$view.removeDuplicates().map{ "view \([=11=])"}.assign(to: \.viewText, on: self).store(in: &cancellables)
}
deinit {
cancellables.forEach { [=11=].cancel() }
}
}
每次重建视图时,都会实例化一个新的视图模型,但不会破坏旧视图模型。 viewText
属性在每个实例上更新 state.$view.removeDuplicates().map{ "view \([=13=])"}.assign(to: \.viewText, on: self).store(in: &cancellables)
如果我不在集合中存储可取消对象,则会调用 deinit
,但如果当前视图的状态已更改,则不会更新 viewText
。
你知道如何在不增加视图模型实例的情况下管理状态的更新吗?
谢谢
您可以使用 sink
而不是 assign
:
state.$view
.removeDuplicates()
.sink { [weak self] in self?.viewText = [=10=] }
.store(in: &cancellables)
但我完全质疑 Combine 的必要性。只需使用计算 属性:
class ViewTextModel: ObservableObject {
@Published var state: AppState
var viewText: String { "view \(state.view)" }
}
更新
如果您的部署目标是 iOS 14(或 macOS 11)或更高版本:
因为您要存储到 @Published
,所以您可以改用 assign(to:)
运算符。它为您管理订阅而不返回 AnyCancellable
.
state.$view
.removeDuplicates()
.map { "view \([=12=])" }
.assign(to: &$viewText)
// returns Void, so nothing to store
我在 viewModels 中使用 Combine 来更新视图。但是,如果我将 AnyCancellable 对象存储到一组 AnyCancellable 中,则永远不会调用 deinit 方法。我使用 deinit 来取消所有可取消对象。
struct View1: View {
@ObservedObject var viewModel:ViewTextModel = ViewTextModel()
@Injected var appActions:AppActions
var body: some View {
VStack {
Text(self.viewModel.viewText)
Button(action: {
self.appActions.goToView2()
}) {
Text("Go to view \(self.viewModel.viewText)")
}
}
}
}
class ViewTextModel: ObservableObject {
@Published var viewText: String
private var cancellables = Set<AnyCancellable>()
init(state:AppState) {
// initial state
viewText = "view \(state.view)"
// updated state
state.$view.removeDuplicates().map{ "view \([=11=])"}.assign(to: \.viewText, on: self).store(in: &cancellables)
}
deinit {
cancellables.forEach { [=11=].cancel() }
}
}
每次重建视图时,都会实例化一个新的视图模型,但不会破坏旧视图模型。 viewText
属性在每个实例上更新 state.$view.removeDuplicates().map{ "view \([=13=])"}.assign(to: \.viewText, on: self).store(in: &cancellables)
如果我不在集合中存储可取消对象,则会调用 deinit
,但如果当前视图的状态已更改,则不会更新 viewText
。
你知道如何在不增加视图模型实例的情况下管理状态的更新吗?
谢谢
您可以使用 sink
而不是 assign
:
state.$view
.removeDuplicates()
.sink { [weak self] in self?.viewText = [=10=] }
.store(in: &cancellables)
但我完全质疑 Combine 的必要性。只需使用计算 属性:
class ViewTextModel: ObservableObject {
@Published var state: AppState
var viewText: String { "view \(state.view)" }
}
更新
如果您的部署目标是 iOS 14(或 macOS 11)或更高版本:
因为您要存储到 @Published
,所以您可以改用 assign(to:)
运算符。它为您管理订阅而不返回 AnyCancellable
.
state.$view
.removeDuplicates()
.map { "view \([=12=])" }
.assign(to: &$viewText)
// returns Void, so nothing to store