SwiftUI:当观察到 object 从另一个文件更改时,视图不更新

SwiftUI: View not updating when Observed object changes from another file

我已经查看了一些类似的问题,但是 none 已经足够接近我的工作状态了。我有 3 个文件:

  1. ContentView.swift
  2. VariableSetupModel.swift
  3. ContentNavView.swift

以前所有 3 个中的代码都在一个文件 (ContentView) 中。我现在正在努力将其拆分以使代码更清晰。我是一个相当新手 iOS 的开发人员。我将所有变量移至 VariableSetupModel 并使其正常工作。我引用该文件中的值,它们更新,并 return 到 ContentView 以更新视图。

现在我正在努力将同一页面上的视图拆分为多个文件,从导航开始。视图显示出来,在页面首次打开时从 VariableSetupModel 正确读取值。但是当值从 ContentView 中的按钮更改时,它不会更新 ContentNavView 中视图的标题。下面是我的代码的简化版本。

ContentView.swift

struct ContentView: View {
    //Pull in variables from "VariableSetupModel"
    @ObservedObject var viewModel = VariableSetupModel()
    
    @State var counter:Int = 0

    
   var body: some View {
        //Main Views
        VStack (alignment: .leading) {
            
        // MARK: Climbs-Title
            ContentNavView()
        }
    }

    Button(action: {
        if viewModel.toggleListGraphs == "graph" {
            viewModel.toggleListGraphs = "list"
        }else{
            viewModel.toggleListGraphs = "graph"
        }        
    }) {
       Image(systemName: "list.bullet.below.rectangle")
           .font(.title)
       }
}

VariableSetupModel.swift

final class VariableSetupModel: ObservableObject {
    static let shared = VariableSetupModel()

    //Visuals
    @Published var toggleListGraphs = "graph"
}

ContentNavView.swift

struct ContentNavView: View {
    //Pull in variables from "VariableSetupModel"
    @ObservedObject var viewModel = VariableSetupModel()
    //var viewModel = VariableSetupModel.shared
    
    var body: some View {
        HStack{
            if viewModel.toggleListGraphs == "graph"{
                Text("All Sends")
                .font(.title)
                .padding(.horizontal)
            }else{
                Text("All Climbs")
                .font(.title)
                .padding(.horizontal)
            }
            
            Spacer()
            
            Button(action: {
                viewModel.showSettingsModal = true
            }) {
                Image("logoIcon")
                    .renderingMode(.original)
                    .resizable()
                    .aspectRatio(contentMode: .fit)
                    .frame(width: 35, height: 35)
            }.padding().foregroundColor(Color("whiteblack"))

        }.sheet(isPresented: $viewModel.showSettingsModal, onDismiss: {
            //print(viewModel.showSettingsModal)
        }) {
            SettingsView()
        }
    }
}

有很多方法可以让 viewModel 变化反映在不同的视图中,下面是一个示例,其主要思想是在所有不同的视图中使用一个真实来源:

ContentView 中声明 @StateObject var viewModel = VariableSetupModel() 并且 @EnvironmentObject var viewModel: VariableSetupModelContentNavView.

通过 viewModel 来自 ContentView to ContentNavView using .environmentObject(viewModel), 即把这个加到ContentView, eg: VStack (alignment: .leading) {...}.environmentObject(viewModel)

注意,VariableSetupModel不需要是单例,去掉static let shared = VariableSetupModel()

另请注意,要在 SettingsView() 中使用 viewModelSettingsView().environmentObject(viewModel)

另一种方法是将 ObservedObject 从一个视图传递到另一个视图。 例如:

ContentView
中声明@StateObject var viewModel = VariableSetupModel() @ObservedObject var viewModel: VariableSetupModelContentNavView.

使用 ContentNavView(viewModel: viewModel).

viewModelContentView 传递到 ContentNavView