从视图模型中更新环境对象



在SwiftUI中,我想将一个环境对象传递给视图模型,以便我可以更改/更新它。envimentobject是一个简单的AppState,由一个属性计数器组成。

class AppState: ObservableObject {
@Published var counter: Int = 0 
}

视图模型"更新环境对象,如下所示:

class CounterViewModel: ObservableObject {

var appState: AppState

init(appState: AppState) {
self.appState = appState
}

var counter: Int {
appState.counter 
}

func increment() {
appState.counter += 1
}

}

ContentView显示值:

struct ContentView: View {

@ObservedObject var counterVM: CounterViewModel

init(counterVM: CounterViewModel) {
self.counterVM = counterVM
}

var body: some View {
VStack {
Text("(counterVM.counter)")
Button("Increment") {
counterVM.increment()
}
}

}
}

我还注入了如下所示的状态:

struct ContentView_Previews: PreviewProvider {
static var previews: some View {
NavigationStack {

let appState = AppState()

ContentView(counterVM: CounterViewModel(appState: appState))
.environmentObject(appState)
}
}
}

问题是,当我点击增量按钮,反虚拟机。计数器永远不会返回更新后的值。我错过了什么?

你的类CounterViewModel是一个ObservableObject,但它没有@Published属性-所以没有任何更改将自动发布到视图

但是你可以使用objectWillChange.send():

手动发布更改
func increment() {
objectWillChange.send()
appState.counter += 1
}

您检查了您的xxxxApp.swift(以前是AppDelegate)文件吗?有时Xcode会自动为你做,有时你不需要手动添加它,并添加你的环境对象。*它必须是包含所有你想要共享对象的视图。

var body: some Scene {
WindowGroup {
VStack {
ContentView()
.environmentObject(YourViewModel())
}
}
}

我们实际上并没有在SwiftUI中为视图数据使用视图模型对象。我们使用@State结构体,如果我们需要在子视图中改变它,我们传递一个绑定,例如

struct Counter {
var counter: Int = 0

mutating func increment() {
counter += 1
}
}
struct ContentView: View {
@State var counter = Counter()

var body: some View {
ContentView2(counter: $counter)
}
}
struct ContentView2: View {
@Binding var counter: Counter // if we don't need to mutate it then just use let and body will still be called when the value changes.
var body: some View {
VStack {
Text(counter.counter, format: .number) // the formatting must be done in body so that SwiftUI will update the label automatically if the region settings change.
Button("Increment") {
counter.increment()
}
}
}
}

我不确定为什么CounterViewModel和AppState都需要是可观察对象,因为您正在使用视图模型来格式化模型的内容。我认为AppState是一个模型,因此我可以将其定义为一个结构体。CounterViewModel将会是ObservableObject并且它发布了AppState。这样你的代码就干净了,可以工作了。

AppState代码:
import Foundation
struct AppState {
var counter: Int = 0
}

代码:

import SwiftUI
class CounterViewModel: ObservableObject {

@Published var appState: AppState

init(appState: AppState) {
self.appState = appState
}

var counter: Int {
appState.counter
}

func increment() {
appState.counter += 1
}
}

ContentView的代码:

import SwiftUI
struct ContentView: View {

@StateObject var counterVM = CounterViewModel(appState: AppState())

var body: some View {
VStack {
Text("(counterVM.counter)")
Button("Increment") {
counterVM.increment()
}
}
}
}

一定要提醒,在你第一次定义ObservableObject的视图中,你用@StateObject来定义它。在所有也将使用该对象的视图中,使用@ObservedObject。

这段代码可以运行。

相关内容

  • 没有找到相关文章

最新更新