SwiftUI 从列表中编辑结构
Posted
技术标签:
【中文标题】SwiftUI 从列表中编辑结构【英文标题】:SwiftUI Edit Struct from List 【发布时间】:2020-11-05 12:41:58 【问题描述】:我正在尝试创建一个列表,当它点击一个单元格时,它会更改 State
对象本身内的 hasBeenSeen
Bool
值。
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
变为@State
var,但这似乎不起作用。我怎样才能使这个Bool
val 可以从列表中编辑?
【问题讨论】:
【参考方案1】:SwiftUI 中的视图是不可变的——它们只是结构——所以你不能改变它们的属性。这就是为什么 SwiftUI 有一个 @State
属性包装器的概念。当您更改“状态”属性时,SwiftUI 实际上会更新状态值,而不是视图的属性值(这也是不可变的)。
因此,您需要在视图中的 states
属性上设置 @State
。 (您还需要更改名称,因为标识符 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]
。
一种方法是对states
的索引执行ForEach
:
var body: some View
NavigationView
List
ForEach(states.indices) index in
StateCell(state: self.$states[index])
.navigationBarTitle(Text("States"))
【讨论】:
以上是关于SwiftUI 从列表中编辑结构的主要内容,如果未能解决你的问题,请参考以下文章
如何从 SwiftUI 的详细信息视图(编辑项目视图)中删除核心数据条目?