在 SwiftUI 中重绘视图时运行

问题描述 投票:0回答:2

我在 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 已经更新为 newValue,并且我无法捕获旧的值。我在文档中读到,这是设计使然,您必须捕获要存储旧值的内容,但我(据我所知)只能捕获 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 观察者来代替,但即使当我捕获 self 时,当调用闭包时,旧值和新值是相同的。

这似乎是一件常见的事情(检测外部变化并触发关闭),我应该如何处理?

swift swiftui binding state
2个回答
3
投票

如果我正确理解了您的需求,那么您应该不在视图中而是在视图模型中执行此操作,例如

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: \($0.someValue)")
    print("New value: \($1.someValue)")
}

0
投票

SwiftUI 根据相关数据的更改自动重绘视图。但是,它不提供重绘通知,即类似

.redrawn()
修饰符的通知。因此,应用程序不能依赖视图来触发某些逻辑;这与 SwiftUI 是声明性的这一事实是一致的。应用程序需要监控数据的变化并相应地触发逻辑。

© www.soinside.com 2019 - 2024. All rights reserved.