0

我试图有一个列表,当它点击一个单元格时,它会更改对象本身的hasBeenSeen Bool值。State

struct State: Identifiable {
    var id = UUID()
    let name: String
    var hasBeenSeen: Bool = false
}

struct ContentView: View {
    let states: [State] = [
        State(name: "Oregon", hasBeenSeen: true),
        State(name: "California", hasBeenSeen: true),
        State(name: "Massachussets", hasBeenSeen: false),
        State(name: "Washington", hasBeenSeen: true),
        State(name: "Georgia", hasBeenSeen: false)
    ]
    
    var body: some View {
        NavigationView {
            List {
                ForEach(states, id: \.id) { state in
                    StateCell(state: state)
                }
            }.navigationBarTitle(Text("States"))
        }
    }
}

struct StateCell: View {
    var state: State
    
    var body: some View {
        HStack {
            Text(state.name)
            Spacer()
            if state.hasBeenSeen {
                Image(systemName: "eye.fill")
            }
        }.onTapGesture {
//            state.hasBeenSeen.toggle()
        }
    }
}

我最初的想法是我需要制作hasBeenSeen一个@Statevar 但这似乎不起作用。如何使这个Boolval 可以从列表中编辑?

4

1 回答 1

0

SwiftUI 中的视图是不可变的——它们只是结构——所以你不能改变它们的属性。这就是为什么 SwiftUI 有一个@State属性包装器的概念。当您更改“状态”属性时,SwiftUI 实际上会更新状态值,而不是视图的属性值(这也是不可变的)。

因此,您需要在视图中设置@State属性states。(您还需要更改名称,因为标识符State已被State属性包装器占用 - 所以我只是将其更改为StateEntity

@State var states: [StateEntity] = [
      StateEntity(name: "Oregon", hasBeenSeen: true),
      // ... etc
   ]

但是,这还不够,因为当您将states数组的一个元素(一个StateEntity值)传递给子视图时,您只是传递了一个副本。

为此,您需要绑定。绑定允许子视图修改父视图的状态属性,而无需拥有数据。因此,子视图的属性应该使用@Binding属性包装器:

struct StateCell: View {
    @Binding var state: StateEntity

    // ...
}

SwiftUI 通过使用投影值(在本例中为$states.

但是,您不需要将绑定传递给整个数组,而是传递给该数组的特定元素。不幸的是(而且相当烦人),这有点棘手。您需要获取元素的索引,并在给定索引的情况下访问绑定,如下所示$state[index]

一种方法是对 进行ForEach过度索引states

var body: some View {
   NavigationView {
      List {
         ForEach(states.indices) { index in
            StateCell(state: self.$states[index])
         }
      }.navigationBarTitle(Text("States"))
   }
}
于 2020-07-16T01:07:40.127 回答