SwiftUI- 将@State 变量传递给多个视图有问题

SwiftUI- passing @State variables to multiple views trouble

我正在尝试制作一款类似于 iPhone 提醒应用的应用 UI。我有一个视图,其中有一个列表,我可以从中添加和删除项目,我还有一个视图用于添加一个项目,允许我命名该项目和 select 一些选项,我还有另一个视图何时列表中的一项是 selected,我希望能够显示我所做的名称和选项,但它没有显示。 列表视图的代码

struct DotView: View {

enum ActiveSheet: String, Identifiable {
    case SwiftUIView, EditView
    var id: String {
        return self.rawValue
    }
}

@EnvironmentObject var listViewModel: ListViewModel
@AppStorage("dotApiKey") var selectedDotApi: String = ""
@State var dotName:String = ""
@State var dotNumber:String = ""
@State var selection:String = ""
@State var triggerSelection:String = ""
@State var searchText:String = ""
@State var plugUsername:String = ""
@State var plugPassword:String = ""
@State var toggleNotification:Bool
@State var activeSheet : ActiveSheet? = nil
    
@Binding var show : Bool

var body: some View {
        ZStack{
            HStack {
                EditButton()
                    .padding(.leading)
                Spacer()
                Button(action: {
                    self.activeSheet = .SwiftUIView
                }, label: {
                    Text("Add")
                })
                    .padding(.trailing)
            }

            ZStack {
                List {
                    ForEach(listViewModel.dotitems, id:\.dotId){ dotitem in
                        Button(action: { self.activeSheet = .EditView }, label: {
                            DotItemListView(dotitem: dotitem)
                        })
                    }
                    .onDelete(perform: listViewModel.deleteItem)
                    .onMove(perform: listViewModel.moveItem)
                    .listRowBackground(Color("textBG"))
                    
                }.listStyle(PlainListStyle())
                .background(Color("textBG"))
                .frame(height: 300)
                .cornerRadius(10)
                .padding(.horizontal)                    
           }
       }
   .sheet(item: $activeSheet){ sheet in
        switch sheet {
        case .SwiftUIView:
            SwiftUIView(dotName: dotName, dotNumber: dotNumber, selection: selection, triggerSelection: triggerSelection, searchText: searchText, plugUsername: plugUsername, plugPassword: plugPassword, show: $show)
        case .EditView:
            EditView(show:$show)
        }
    }

当我向列表中添加一个项目时,它会在每一行中显示此项目

struct DotItemListView:View {
let dotitem: DotItem

var body: some View{
    HStack {
        Text(dotitem.dotName)
        Spacer()
        Text(dotitem.selection)
        Spacer()
        Text(dotitem.dotNumber)
        Spacer()
    }
}

}

这就是我将每个项目添加到列表的方式

struct DotItem:Equatable, Codable{
var dotId = UUID().uuidString
let dotName:String
let dotNumber:String
let selection:String
}

class ListViewModel: ObservableObject {

@Published var dotitems: [DotItem] = [] {
    didSet {
        saveItem()
    }
}
let dotitemsKey: String = "dotitems_list"

init() {
    getDotItems()
}

func getDotItems() {
    guard
        let data = UserDefaults.standard.data(forKey: dotitemsKey),
        let savedDotItems = try? JSONDecoder().decode([DotItem].self, from: data)
    else { return }
    
    self.dotitems = savedDotItems
}

func deleteItem(indexSet: IndexSet){
    dotitems.remove(atOffsets: indexSet)
}

func moveItem(from: IndexSet, to: Int){
    dotitems.move(fromOffsets: from, toOffset: to)
}

func addItem(dotName: String, dotNumber: String, selection: String){
    let newItem = DotItem(dotName: dotName, dotNumber: dotNumber, selection: selection)
    dotitems.append(newItem)
    
    print(newItem)
}

func saveItem() {
    if let encodedData = try? JSONEncoder().encode(dotitems) {
        UserDefaults.standard.set(encodedData, forKey: dotitemsKey)
    }
}
}

这是我为每个项目输入数据的视图

struct SwiftUIView: View {

@Environment(\.presentationMode) var presentationMode
@EnvironmentObject var listViewModel: ListViewModel
@AppStorage("dotApiKey") var selectedDotApi: String = ""
@State var dotName:String
@State var dotNumber:String
@State var selection:String
@State var triggerSelection:String
@State var selectedColor = Color.black
@State var searchText:String
@State var plugUsername:String
@State var plugPassword:String
@ObservedObject var vm = getDeviceNames()
@State var triggerDot:Bool = false
@State var toggleOnOff:Bool = false
@State var toggleLightColor:Bool = false
@State var isSearching:Bool = false

@StateObject var camera = CameraModel()

@Binding var show : Bool

var body: some View {
    NavigationView {
                    Form {
                        Section(header: Text("Info")) {
                            TextField("Name", text: $dotName)
                            TextField("Number", text: $dotNumber)
                            Picker(selection: $selection, label: Text("Discover Plug")) {
                                ForEach(vm.dataSet, id:\.self) { item in
                                    Text(item.Device).tag(item.Device)
                                }
                            }
                            Toggle(isOn: $isSearching, label: {
                                Text("Have smart plugs?")
                            })
                            if isSearching {
                                HStack{
                                    Text("Casa")
                                    Spacer()
                                    Button(action: {sendPlugDict()}, label: {
                                        Text("Login")
                                    })
                                }
                                TextField("Username", text: $plugUsername)
                                TextField("Password", text: $plugPassword)
                                
                            }
                        }
                        Section {
                            Toggle(isOn: $toggleOnOff, label: {
                                Text("On/Off")
                            })
                        }
                        Section {
                            Toggle(isOn: $toggleLightColor, label: {
                                Text("Light Color")
                            })
                            if toggleLightColor {
                                ColorPicker("Choose Light Color", selection: $selectedColor)
                            }
                        }
                        Section {
                            if listViewModel.dotitems.isEmpty == false {
                                Toggle(isOn: $triggerDot, label: {
                                    Text("Add a DOT to trigger")
                                })
                                if triggerDot {
                                    Picker(selection: $triggerSelection, label: Text("Select DOT")) {
                                        ForEach(listViewModel.dotitems, id:\.dotId){ dotitem in
                                            DotItemListView(dotitem: dotitem)
                                        }
                                    }
                                }
                            }
                        }
                    }
                    .navigationBarTitle("")
                    .navigationBarHidden(true)
                }
}
}

这是我试图在 selected 任何列表项时显示数据的视图,除了少数地方

与上面基本相同
struct EditView: View {
@Environment(\.presentationMode) var presentationMode
@EnvironmentObject var listViewModel: ListViewModel
@ObservedObject var vm = getDeviceNames()
@State var dataSet = [Result]()
@State var dotName:String = ""
@State var dotNumber:String = ""
@State var selection:String = ""
@State var triggerSelection:String = ""
@State var selectedColor = Color.black
@State var searchText:String = ""
@State var plugUsername:String = ""
@State var plugPassword:String = ""
@State var triggerDot:Bool = false
@State var toggleOnOff:Bool = false
@State var toggleLightColor:Bool = false
@State var isSearching:Bool = false

@Binding var show : Bool

var body: some View {
    NavigationView {
                    Form {
                        Section(header: Text("Info")) { 
                            TextField(dotName, text: $dotName)
                            TextField(dotNumber, text: $dotNumber)
                            Picker(selection: $selection, label: Text("Discorver Plug")) {
                                ForEach(dataSet, id:\.self) { item in
                                    Text(item.Device).tag(item.Device)
                                }
                            }
                            Toggle(isOn: $isSearching, label: {
                                Text("Have smart plugs?")
                            })
                            if isSearching {
                                HStack{
                                    Text("Casa")
                                    Spacer()
                                    Button(action: {
                                            SwiftUIView(dotName: dotName, dotNumber: dotNumber, selection: selection, triggerSelection: triggerSelection, searchText: searchText, plugUsername: plugUsername, plugPassword: plugPassword, show: $show).sendPlugDict()}, label: {
                                        Text("Login")
                                    })
                                }
                                TextField("Username", text: $plugUsername)
                                TextField("Password", text: $plugPassword)
                                
                            }
                        }
                        Section {
                            Toggle(isOn: $toggleOnOff, label: {
                                Text("On/Off")
                            })
                        }
                        Section {
                            Toggle(isOn: $toggleLightColor, label: {
                                Text("Light Color")
                            })
                            if toggleLightColor {
                                ColorPicker("Choose Light Color", selection: $selectedColor)
                            }
                        }
                        Section {
                            if listViewModel.dotitems.isEmpty == false {
                                Toggle(isOn: $triggerDot, label: {
                                    Text("Add a DOT to trigger")
                                })
                                if triggerDot {
                                    Picker(selection: $triggerSelection, label: Text("Select DOT")) {
                                        ForEach(listViewModel.dotitems, id:\.dotId){ dotitem in
                                            DotItemListView(dotitem: dotitem)
                                        }
                                    }
                                }
                            }
                        }
                    }
                    .navigationBarTitle("")
                    .navigationBarHidden(true)
                }

}
}

我知道这有很多事情要做,但我们将不胜感激

在要将状态传递给的视图上使用@Binding。

视图 1:

@State var a = true 

View2(a: $a)

视图 2:

@Binding var a : Bool

要在全球范围内传递数据,请使用@EnvoirmentObject :

示例:

@main
struct YourApp: App {

    @StateObject var session = Session()
    
    var body: some Scene {
        WindowGroup {
            SplashView()
                .environmentObject(session)
        }
    }
}

会话:

class Session: ObservableObject {

    /// user signin state
    @Published  var isSignedIn : Bool = false
}

视图 1,视图 2,视图 3 ....:

struct SplashView: View {
    
    @EnvironmentObject var session : Session
    
    var body: some View {
        VStack{
            SignInView()
                .opacity(session.isSignedIn ? 0:1)
        }
        .background(Color.background.ignoresSafeArea())
    }
}