swiftui - SwiftUI 中的可扩展列表只会扩展一次,不会收缩

标签 swiftui swiftui-list

我正在尝试(但失败了!)在 SwiftUI 中实现可扩展的问答列表。

struct FAQ: Equatable, Identifiable {
    static func ==(lhs: FAQ, rhs: FAQ) -> Bool {
        return lhs.id == rhs.id
    }
    let id = UUID()
    let question: String
    let answers: [String]
    var isExpanded: Bool = false
}

struct ContentView: View {
    @State private (set) var faqs: [FAQ] = [
        FAQ(question: "What is the fastest animal on land?", answers: ["The cheetah"]),
        FAQ(question: "What colours are in a rainbox?", answers: ["Red", "Orange", "Yellow", "Blue", "Indigo", "Violet"])
    ]

    var body: some View {
        List {
            ForEach(faqs) { faq in
                Section(header: Text(faq.question)
                    .onTapGesture {
                        if let index = self.faqs.firstIndex(of: faq) {
                            self.faqs[index].isExpanded.toggle()
                        }
                    }
                ) {
                    if faq.isExpanded {
                        ForEach(faq.answers, id: \.self) {
                            Text("• " + $0).font(.body)
                        }
                    }
                }
            }
        }
    }
}

成功点击任何问题都会将答案展开,但再次点击同一个标题不会缩小答案,点击第二个问题也不会展开这些答案。

enter image description here

通过一些巧妙放置的 print,我可以看到 isExpanded 在第一个问题被点击时切换到 true,但随后不会t 切换回 false

有人可以解释我做错了什么吗?

最佳答案

问题出在您的 @State var faq: [FAQ] 行。 @State 属性包装器允许您的 View 监视数组中的更改,但更改数组元素之一的属性不算作数组中的更改。

您可能不想使用状态变量,而是想创建一个小 View 模型,如下所示:

class ViewModel: ObservableObject {
    @Published var faqs: [FAQ] = [
           FAQ(question: "What is the fastest animal on land?", answers: ["The cheetah"]),
           FAQ(question: "What colours are in a rainbox?", answers: ["Red", "Orange", "Yellow", "Blue", "Indigo", "Violet"])
       ]
}

并更新您的 ContentView:

struct ContentView: View {
    @ObservedObject var model = ViewModel()

    var body: some View {
        List {
            ForEach(model.faqs.indices) { index in
                Section(header: Text(self.model.faqs[index].question)
                    .onTapGesture {
                        self.model.faqs[index].isExpanded.toggle()
                    }
                ) {
                    if self.model.faqs[index].isExpanded {
                        ForEach(self.model.faqs[index].answers, id: \.self) {
                            Text("• " + $0).font(.body)
                        }
                    }
                }
            }
        }
    }
}

ContentView 中的 @ObservedObject 属性包装器现在监视其 ViewModel 对象宣布的任何更改,并且 @Published 包装器告诉 ViewModel 类宣布数组发生的任何事情,包括对其元素的更改。

关于swiftui - SwiftUI 中的可扩展列表只会扩展一次,不会收缩,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58064377/

相关文章:

swiftui - 使用实时数据滚动时 SwiftUI 列表非常慢

ios - 从托管 View Controller 委托(delegate) SwiftUI View

ios - 网络请求后 SwiftUI 更新 Elements.count

swift - 如何仅使用文本字段使按钮可单击到另一个 View Controller

autocomplete - 如何使用 ZStack & Geometry 定位列表?

swiftui - 无法推断通用参数 'SelectionValue'

SwiftUI ForEach 类型 '_' 没有成员 'id'

ios - SwiftUI 导航栏和状态栏 - 让它们颜色相同

ios - Swift MKMapView.setRegion 在 MKLocalSearch.Request 之后不起作用

xcode - SwiftUI:listRowInsets 未按预期工作