无法跨导航视图更改变量

Can't change variable across Navigationviews

我有一个按钮应该更改另一个 class 中的变量,一旦更改,读取此变量的其他 NavigationView 也需要更改。如果有帮助,需要到处更新的变量是 UIColor。

这是按钮:

struct SettingsView: View {

@State private var colorToggle = 0
    
    func colorToggleButton() {
        // color toggle logic
        if colorToggle == 0 {
           colorToggle += 1
        }
        else if colorToggle == 1 {
            colorToggle -= 1
        }
    }
    
    func colorToggleLogic() {
        if colorToggle == 0 {
            viewModel.backgroundColor = .white
        }
        else if colorToggle == 1 {
            viewModel.backgroundColor = .orange
        }
    }


        Button(action: {
            colorToggleButton()
            colorToggleLogic()
        }, label: {
            Text("Color")
        }).offset(x: -5, y: 0)
}

这是 backgroundColor 变量所在的 ViewModel:

class VariableViewModel: ObservableObject {
@Published var backgroundColor: UIColor = .white
}

这是变量需要更新但在更改时由于某种原因无法正常工作的地方:

struct ContentView: View {
  
    // variable for view model
@ObservedObject var viewModel = VariableViewModel()
    
    var body: some View {
NavigationView {

ZStack {
  Color(viewModel.backgroundColor)
HStack {
                Spacer()
            NavigationLink(destination:
                SettingsView()
            ){
                Image(systemName: "gearshape.fill").font(.system(size: 25))
            }
}
}
}
}

您可以尝试使用 State 变量,而不是使用 ObservableObject。你可以试试这个:

struct ContentView: View {
  
    // variable for view model
@State var backgroundColor: Color = .white
    
    var body: some View {
NavigationView {

ZStack {
  Color(backgroundColor)
HStack {
                Spacer()
            NavigationLink(destination:
                SettingsView(parent: self)
            ){
                Image(systemName: "gearshape.fill").font(.system(size: 25))
            }
}
}
}
}

你应该将 SettingsView 更新为:

struct SettingsView: View {

@State var parent: ContentView
@State private var colorToggle = 0
    
    func colorToggleButton() {
        // color toggle logic
        if colorToggle == 0 {
           colorToggle += 1
        }
        else if colorToggle == 1 {
            colorToggle -= 1
        }
    }
    
    func colorToggleLogic() {
        if colorToggle == 0 {
            parent.backgroundColor = .white
        }
        else if colorToggle == 1 {
            parent.backgroundColor = .orange
        }
    }


        Button(action: {
            colorToggleButton()
            colorToggleLogic()
        }, label: {
            Text("Color")
        }).offset(x: -5, y: 0)
}

这让您可以在任何地方使用 ContentView 中的 State 变量。同样,您只需要添加一个名为 parent 的 State var 或您选择的 ContentView 类型的其他内容,以便您可以访问 backgroundColor 属性.

另一种方法是将颜色选择写入文件并在视图中添加额外的代码来处理它。

例如:

struct SettingsView: View {

@State private var colorToggle = 0
    
    func colorToggleButton() {
        // color toggle logic
        if colorToggle == 0 {
           colorToggle += 1
        }
        else if colorToggle == 1 {
            colorToggle -= 1
        }
    }
    
    func colorToggleLogic() {
        if colorToggle == 0 {
            let url = FileManager.default.urls(for .documentsDirectory, in: .userDomainMask).first!.appendingPathComponent("ColorSelection.txt")
            do {
                try "white".data(using: .utf8)!.write(to: url)
            }
            catch {
                //handle error
            }
        }
        else if colorToggle == 1 {
            let url = FileManager.default.urls(for .documentsDirectory, in: .userDomainMask).first!.appendingPathComponent("ColorSelection.txt")
            do {
                try "orange".data(using: .utf8)!.write(to: url)
            }
            catch {
                //handle error
            }
        }
    }


        Button(action: {
            colorToggleButton()
            colorToggleLogic()
        }, label: {
            Text("Color")
        }).offset(x: -5, y: 0)
}

并且在 ContentView 或您需要背景颜色的任何其他视图中,您可以添加以下内容:

func processColor() {
    let url = FileManager.default.urls(for: .documentsDirectory, in: .userDomainMask).first!.appendingPathComponent("ColorSelection.txt")
    do {
        let color = try Data(contentsOf: url)
        if String(data: color, encoding: .utf8)! == "white" {
            // set background to white
        }
        else {
            // set background to orange
        } 
    }
    catch {
        //handle error
    }
}

编辑:

响应 OP 的评论之一询问如何在不退出和返回的情况下更新设置视图,可以使用以下代码:

struct SettingsView: View {

@State var parent: ContentView
@State private var colorToggle = 0
@State var backgroundColor = .white

    func colorToggleButton() {
        // color toggle logic
        if colorToggle == 0 {
           colorToggle += 1
        }
        else if colorToggle == 1 {
            colorToggle -= 1
        }
    }

    func colorToggleLogic() {
        if colorToggle == 0 {
            parent.backgroundColor = .white
            self.backgroundColor = .white
        }
        else if colorToggle == 1 {
            parent.backgroundColor = .orange
            self.backgroundColor = .orange
        }
    }


        Button(action: {
            colorToggleButton()
            colorToggleLogic()
        }, label: {
            Text("Color")
        }).offset(x: -5, y: 0).onAppear {
            self.backgroundColor = parent.backgroundColor
        }
}

这将创建一个新变量来控制设置视图本身的背景颜色,这样就无需退出视图并重新进入。