代码之家  ›  专栏  ›  技术社区  ›  Atharv Salokhe

添加选择器以更改Observable类中的数据

  •  1
  • Atharv Salokhe  · 技术社区  · 8 月前

    我试图使用选择器通过自定义结构更改存储在类中的值。我正在尝试制作一个列出课程名称和成绩的应用程序。拾取器位于一个名为HStack的文件夹中。我无法使用选择器更改特定元素(在本例中为grade)的值。我使用Observable类,因为我有多个视图需要访问该类。

    这是我的一些代码,

    struct courseItem: Identifiable{
        var id = UUID()
        let name: String
        let grade: String
    }
    @Observable
    class Courses{
        var items = [courseItem]()
    }
    struct ContentView: View{
        @State private var courses = Courses()
        let grades = ["A", "B", "C"]
        var body: some View{
            List{
                ForEach(courses.items){ item in 
                    HStack{
                        Text(item.name)
                        Spacer()
                        Picker("Grade", selection: item.grade){
                            ForEach(grades, id: \.self){
                                Text($0)
                            }
                        }
                    }
                }
         
            }
        }
    }
    

    我知道 item.grade 应该是有约束力的,但我这样做时出错了。现在我收到一个错误,说编译器无法在合理的时间内对表达式进行类型检查。任何帮助都将不胜感激。

    1 回复  |  直到 8 月前
        1
  •  1
  •   workingdog support Ukraine    8 月前

    尝试使用绑定的方法 $ 如示例代码所示, ...to change the value of a particular element, (in this example, grade)

    struct courseItem: Identifiable {
        let id = UUID()  // <--- here
        var name: String
        var grade: String  // <--- here
    }
    
    @Observable class Courses {
        // <--- for testing
        var items: [courseItem] = [courseItem(name: "name-1", grade: "A"),
                                   courseItem(name: "name-2", grade: "B"),
                                   courseItem(name: "name-3", grade: "C")
        ]
    }
    
    struct ContentView: View {
        @State private var courses = Courses()
        
        let grades = ["A", "B", "C"]
        
        var body: some View{
            List{
                ForEach($courses.items){ $item in   // <--- here
                    HStack{
                        Text(item.name)
                        Spacer()
                        Picker("Grade", selection: $item.grade) {  // <--- here
                            ForEach(grades, id: \.self) {
                                Text($0)
                            }
                        }
                    }
                }
            }
        }
    }
    

    如果你想通过 courses 对于其他视图,您可以使用 @Bindable var courses: Courses 以允许编辑所需的属性,例如:

    struct ContentView: View {
        @State private var courses = Courses() // <--- here, only one source of truth data
    
        var body: some View {
            TestOtherView(courses: courses) // <--- here
        }
    }
    
    struct TestOtherView: View {
        @Bindable var courses: Courses  // <--- here
        
        let grades = ["A", "B", "C"]
        
        var body: some View {
            List{
                ForEach($courses.items){ $item in   // <--- here
                    HStack{
                        Text(item.name)
                        Spacer()
                        Picker("Grade", selection: $item.grade) {  // <--- here
                            ForEach(grades, id: \.self) {
                                Text($0)
                            }
                        }
                    }
                }
            }
        }
    }
    

    注意,如果你想通过 课程 对于许多其他观点,考虑使用 @Environment(Courses.self) private var courses 请参阅以下文档 Managing model data in your app .

    例如:

    struct ContentView: View{
        @State private var courses = Courses()
    
        var body: some View{
            TestOtherView()
                .environment(courses) // <--- here
        }
    }
    
    struct TestOtherView: View{
        @Environment(Courses.self) private var courses  // <--- here
        let grades = ["A", "B", "C"]
        
        var body: some View{
            @Bindable var courses = courses  // <--- here
            List{
                ForEach($courses.items){ $item in   // <--- here
                    HStack{
                        Text(item.name)
                        Spacer()
                        Picker("Grade", selection: $item.grade) {  // <--- here
                            ForEach(grades, id: \.self) {
                                Text($0)
                            }
                        }
                    }
                }
            }
        }
    }