SwiftUI 中的绑定无法在循环内工作
Posted
技术标签:
【中文标题】SwiftUI 中的绑定无法在循环内工作【英文标题】:Binding in SwiftUI fails to work inside of a loop 【发布时间】:2020-04-27 18:02:00 【问题描述】:根据我的理解,我编写了以下代码,用于展开/折叠列表中的一个部分。
struct WORKING_CollapsableListView: View
@State var sectionExpansionStates = [true, true, true]
var body: some View
VStack
List
Section(header: CollapsableSectionHeader(expansionState: self.$sectionExpansionStates[0]))
if self.sectionExpansionStates[0]
ForEach(0..<10) item in
Text("\(item) is \(self.sectionExpansionStates[0] ? "Expanded" : "Collapsed")")
.frame(height: self.sectionExpansionStates[0] ? 10 : 10)
Section(header: CollapsableSectionHeader(expansionState: self.$sectionExpansionStates[1]))
if self.sectionExpansionStates[1]
ForEach(0..<10) item in
Text("\(item) is \(self.sectionExpansionStates[1] ? "Expanded" : "Collapsed")")
.frame(height: self.sectionExpansionStates[1] ? 10 : 10)
Section(header: CollapsableSectionHeader(expansionState: self.$sectionExpansionStates[2]))
if self.sectionExpansionStates[2]
ForEach(0..<10) item in
Text("\(item) is \(self.sectionExpansionStates[2] ? "Expanded" : "Collapsed")")
.frame(height: self.sectionExpansionStates[2] ? 10 : 10)
struct CollapsableSectionHeader: View
@Binding var expansionState: Bool
var body: some View
Button(action:
self.expansionState.toggle()
)
Text("HEADER: \(expansionState ? "Expanded" : "Collapsed")")
.bold()
这按预期工作。但是,以下代码不起作用。我所做的只是用ForEach
替换了多个部分。这段代码的行为应该是相同的,但是当我点击部分标题时没有任何反应。我错过了什么?好像绑定不起作用。
struct NOT_WORKING_CollapsableListView: View
@State var sectionExpansionStates = [true, true, true]
var body: some View
VStack
List
ForEach(0 ..< 3) section in
Section(header: CollapsableSectionHeader(expansionState: self.$sectionExpansionStates[section]))
if self.sectionExpansionStates[section]
ForEach(0..<10) item in
Text("\(item) is \(self.sectionExpansionStates[section] ? "Expanded" : "Collapsed")")
.frame(height: self.sectionExpansionStates[section] ? 10 : 10)
【问题讨论】:
【参考方案1】:这是由于 statically_ranged_ForEach... 正如我在这里所经历的那样,它是 SwiftUI 中最令人困惑的概念。无论如何 - 解决方案是对部分使用显式模型的动态容器。
这是您的代码的简化工作演示(但这个想法应该很容易被您未提供的组件采用)。
使用 Xcode 11.4 / ios 13.4 测试
// simple demo model for sections
struct SectionModel: Identifiable
let id: Int
var expanded = true
struct TestCollapsableListView: View
// dynamic container with model, state is triggered
@State var sections = [SectionModel(id: 0), SectionModel(id: 1), SectionModel(id: 2)]
var body: some View
VStack
List
ForEach(sections) section in
Section(header: Button("Section \(section.id)") self.sections[section.id].expanded.toggle() )
if section.expanded
ForEach(0..<10) item in
Text("\(item) is \(section.expanded ? "Expanded" : "Collapsed")")
.frame(height: section.expanded ? 10 : 10)
【讨论】:
谢谢!哇。这令人难以置信。在我的实际代码中,我使用了类似的状态模型,但我现在看到的唯一区别是我使用的是 ForEach 中的索引,而不是section.id
,它有效!这件事太微妙了,我自己是想不通的。以上是关于SwiftUI 中的绑定无法在循环内工作的主要内容,如果未能解决你的问题,请参考以下文章
SwiftUI ListView 没有访问 ForEach 循环