1

我是一个新手,正在开发一个基本上有一个冰箱类的应用程序,其中包含食物。我正在尝试使用一个带有食物清单的冰箱。所以我将foodList设置为一个已发布的对象,并在程序启动时实例化一个 @StateObject 冰箱。基本上,从我的角度来看,每当foodList发生变化时,冰箱对象都会保存它的状态并给我一个新的视图。

另外,我想将此@StateObject 冰箱传递给另一个视图,以便我的另一个视图可以修改冰箱中的foodList

下面是我的代码

struct ContentView: View {
    @StateObject private var fridge=Fridge();
    private var dbStartWith=0;
    
    @State private var selection = 1;
    @State private var addFood = false;
    
    var body: some View {
        TabView(selection: $selection) {
            NavigationView {
                List(fridge.container!){
                    food in NavigationLink(destination: FoodView()) {
                        Text("HI")
                    }
                }.navigationBarTitle(Text("Fridge Items"), displayMode: .inline)
                .navigationBarItems(trailing:
                                        NavigationLink(destination: AddFoodView(fridgeView: fridge)) {
                                            Image(systemName: "plus.circle").resizable().frame(width: 22, height: 22)
                                        } )
            }
            .tabItem {
                Image(systemName: "house.fill")
                Text("Home")
            }
            .tag(1)
            
            
            Text("random tab")
                .font(.system(size: 30, weight: .bold, design: .rounded))
                .tabItem {
                    Image(systemName: "bookmark.circle.fill")
                    Text("profile")
                }
                .tag(0)
        }
        
    }
}
    

struct FoodView: View{
    var body: some View{
        NavigationView{
            Text("food destination view ");
        }
    }
}

struct AddFoodView: View{
    @ObservedObject var fridgeView: Fridge;
    @State private var name = ""
    @State private var count : String = "1"
    @State private var category : String = "肉类";
    @State var showCategory = false
    @State var showCount = false
    

    var body: some View{
        ZStack{
            NavigationView{
                Form{
                    HStack{
                        Text("食品")
                        TextField("请输入材料名", text: $name);
                    }.padding(.bottom,10).padding(.top,10).padding(.leading,10).padding(.trailing,10)
                    HStack{
                        Text("数量")
                        TextField("请选择数量",text:$count,onEditingChanged:{(changed) in
                            self.hideKeyboard();
                            self.showCount=changed;
                        }){}
                    }.padding(.bottom,10).padding(.top,10).padding(.leading,10).padding(.trailing,10)
                    HStack{
                        Text("种类")
                        TextField("请选择种类",text: $category,onEditingChanged:{(changed) in
                            self.hideKeyboard();
                            self.showCategory=changed;
                        }){}
                    }.padding(.bottom,10).padding(.top,10).padding(.leading,10).padding(.trailing,10)
                }
            }.navigationBarItems(trailing: NavigationLink(destination: FoodView()){
                Text("保存").foregroundColor(Color.blue).font(.system(size: 18,design: .default))
            }).simultaneousGesture(TapGesture().onEnded{
                var tempFood=Food(id: fridgeView);//not completed yet
            })
            ZStack{
                    if self.showCount{
                        Rectangle().fill(Color.gray)
                            .opacity(0.5)
                        VStack(){
                            Spacer(minLength: 0);
                            HStack{
                                Spacer()
                                Button(action: {
                                    self.showCount=false;
                                }, label: {
                                    Text("Done")
                                }).frame(alignment: .trailing).offset(x:-15,y:15)
                            }
                            Picker(selection: $count,label: EmptyView()) {
                                ForEach(1..<100){ number in
                                    Text("\(number)").tag("\(number)")
                                }
                            }.labelsHidden()
                        }            .frame(minWidth: 300, idealWidth: 300, maxWidth: 300, minHeight: 250, idealHeight: 100, maxHeight: 250, alignment: .top).fixedSize(horizontal: true, vertical: true)
                        .background(RoundedRectangle(cornerRadius: 27).fill(Color.white.opacity(1)))
                        .overlay(RoundedRectangle(cornerRadius: 27).stroke(Color.black, lineWidth: 1))
                        .offset(x:10,y:-10)
                        Spacer()
                    }
                    if self.showCategory{
                        let categoryArr = ["肉类","蔬菜类&quot;,"饮料类&quot;,"调味品类"]
                        ZStack{
                            Rectangle().fill(Color.gray)
                                .opacity(0.5)
                            VStack(){
                                Spacer(minLength: 0);
                                HStack{
                                    Spacer()
                                    Button(action: {
                                        self.showCategory=false;
                                    }, label: {
                                        Text("Done")
                                    }).frame(alignment: .trailing).offset(x:-15,y:15)
                                }
                                Picker(selection: $category,label: EmptyView()) {
                                    ForEach(0..<categoryArr.count){ number in
                                        Text(categoryArr[number]).tag(categoryArr[number])
                                    }
                                }.labelsHidden()
                            }            .frame(minWidth: 300, idealWidth: 300, maxWidth: 300, minHeight: 250, idealHeight: 100, maxHeight: 250, alignment: .top).fixedSize(horizontal: true, vertical: true)
                            .background(RoundedRectangle(cornerRadius: 27).fill(Color.white.opacity(1)))
                            .overlay(RoundedRectangle(cornerRadius: 27).stroke(Color.black, lineWidth: 1))
                            Spacer()
                        }.offset(x:10,y:20)
                    }
            }
        }.animation(.easeInOut)
    }
        
    
}

基本上我想将 传递@StateObject private var fridgestruct AddFoodView: View以便我AddFoodView可以使用该变量。根据我在网上了解到的情况,我认为我需要这样@ObservedObjects注入NavigationLink(destination: AddFoodView(fridgeView: fridge))。这不会给我带来让我困惑的错误(至少在调试器阶段)。不是fridge一个Food变量和 fridgeView一个@ObservedObject Food变量吗?

如果我做这样的事情AddFoodView(fridgeView: $fridge))。有一个错误说Cannot convert value '$fridge' of type 'ObservedObject<Fridge>.Wrapper' to expected type 'Fridge', use wrapped value instead

4

1 回答 1

1

@StateObject并且@ObservedObject是事实的来源,它们彼此非常相似并且几乎可以互换。

要与其他Views 共享这些,您应该将其传递给AddFoodViewusing.environmentObject(fridge)并将@ObservedObject var fridgeView: Fridge;in更改AddFoodView@EnvironmentObject var fridgeView: Fridge

查找有关“在您的应用程序中管理模型数据”的 Apple 文档。

struct BookReader: App {
    @StateObject var library = Library()

    var body: some Scene {
        WindowGroup {
        LibraryView()
                .environmentObject(library)
        }
    }
}

struct LibraryView: View {
    @EnvironmentObject var library: Library

    // ...
}

另一个很好的来源是 Apple SwiftUI 教程,尤其是“处理用户输入”

于 2020-12-27T15:11:08.410 回答