运行 当视图在 SwiftUI 中重绘时
run when a view redraws in SwiftUI
我在 SwiftUI 中有一个视图,我希望它在我的模型中的变量发生变化时重绘和 运行 闭包。我正在使用这个闭包来更新我存储在视图中的状态变量,它应该是我的模型中变量在它改变之前的先前值
下面的代码模拟了我的情况:
let viewModel = ViewModel()
struct someView: View {
@observedObject var viewModel: ViewModel = viewModel
@State var previousSomeValue: CGFloat = 0
var body: some View {
Text("\(viewModel.model.someValue)")
}
}
class ViewModel: ObservableObject {
@Published var model = Model()
}
struct model {
var someValue: CGFloat = 0
}
使用此设置,如果 someValue 发生变化,someView 会重绘,但是,我无法触发关闭。
//我尝试过的解决方案:
最主要的是附上 onChangeOf(_ (T)->Void)
我的观点。使用 .onChangeOf( viewModel.model.someValue ) { _ in //do something }
我可以在它发生变化时触发闭包,但是,当它 运行、viewModel.model.someValue 已经更新到新值时,我无法捕获旧值。我在文档中读到这是设计使然,你必须捕获你想要存储旧值的东西,但我(据我所知)只能捕获 self,viewModel,但不能捕获 viewModel.model.someValue。
.onChangeOf( viewModel.model.someValue ) { [self] newValue in //do something } //works but doesnt capture the var
.onChangeOf( viewModel.model.someValue ) { [viewModel] newValue in //do something } //works but doesnt capture the var
.onChangeOf( viewModel.model.someValue ) { [viewModel.model.someValue] newValue in //do something } //does not compile ( Expected 'weak', 'unowned', or no specifier in capture list )
我也试过在视图中创建一个绑定,例如 Binding { gameView.model.someValue } set: { _ in }
并让 onChange 观察者 this 代替,但即使当我捕获自我时,当调用闭包时,旧值和新值是相同的.
这似乎是一件很常见的事情(检测外部变化并触发关闭),我应该怎么做?
如果我正确理解了您的需求,那么您应该不在视图中而是在视图模型中执行此操作,例如
class ViewModel: ObservableObject {
var onModelChanged: (_ old: Model, _ new: Model) -> Void
@Published var model = Model() {
didSet {
onModelChanged(oldValue, model)
}
}
init(onModelChanged: @escaping (_ old: Model, _ new: Model) -> Void = {_, _ in}) {
self.onModelChanged = onModelChanged
}
}
因此实例化 ViewModel
您可以提供回调以观察模型中更改的值并具有旧值和新值,例如
@StateObject var viewModel = ViewModel() {
print("Old value: \([=11=].someValue)")
print("New value: \(.someValue)")
}
我在 SwiftUI 中有一个视图,我希望它在我的模型中的变量发生变化时重绘和 运行 闭包。我正在使用这个闭包来更新我存储在视图中的状态变量,它应该是我的模型中变量在它改变之前的先前值
下面的代码模拟了我的情况:
let viewModel = ViewModel()
struct someView: View {
@observedObject var viewModel: ViewModel = viewModel
@State var previousSomeValue: CGFloat = 0
var body: some View {
Text("\(viewModel.model.someValue)")
}
}
class ViewModel: ObservableObject {
@Published var model = Model()
}
struct model {
var someValue: CGFloat = 0
}
使用此设置,如果 someValue 发生变化,someView 会重绘,但是,我无法触发关闭。
//我尝试过的解决方案:
最主要的是附上 onChangeOf(_ (T)->Void)
我的观点。使用 .onChangeOf( viewModel.model.someValue ) { _ in //do something }
我可以在它发生变化时触发闭包,但是,当它 运行、viewModel.model.someValue 已经更新到新值时,我无法捕获旧值。我在文档中读到这是设计使然,你必须捕获你想要存储旧值的东西,但我(据我所知)只能捕获 self,viewModel,但不能捕获 viewModel.model.someValue。
.onChangeOf( viewModel.model.someValue ) { [self] newValue in //do something } //works but doesnt capture the var
.onChangeOf( viewModel.model.someValue ) { [viewModel] newValue in //do something } //works but doesnt capture the var
.onChangeOf( viewModel.model.someValue ) { [viewModel.model.someValue] newValue in //do something } //does not compile ( Expected 'weak', 'unowned', or no specifier in capture list )
我也试过在视图中创建一个绑定,例如 Binding { gameView.model.someValue } set: { _ in }
并让 onChange 观察者 this 代替,但即使当我捕获自我时,当调用闭包时,旧值和新值是相同的.
这似乎是一件很常见的事情(检测外部变化并触发关闭),我应该怎么做?
如果我正确理解了您的需求,那么您应该不在视图中而是在视图模型中执行此操作,例如
class ViewModel: ObservableObject {
var onModelChanged: (_ old: Model, _ new: Model) -> Void
@Published var model = Model() {
didSet {
onModelChanged(oldValue, model)
}
}
init(onModelChanged: @escaping (_ old: Model, _ new: Model) -> Void = {_, _ in}) {
self.onModelChanged = onModelChanged
}
}
因此实例化 ViewModel
您可以提供回调以观察模型中更改的值并具有旧值和新值,例如
@StateObject var viewModel = ViewModel() {
print("Old value: \([=11=].someValue)")
print("New value: \(.someValue)")
}