【问题标题】:How to show list of views from a dataSource like UITableView in SwiftUI如何在 SwiftUI 中显示来自数据源(如 UITableView)的视图列表
【发布时间】:2019-11-01 10:31:21
【问题描述】:

在 SwiftUI 中,我们有 List 来表示可重复使用的项目。就像UIKit 中的UITableView

静态列表构建如下:

List {
    Text("cell")
    Text("cell")
    Text("cell")
    Text("cell")
}

但似乎它根本不可重复使用

如何拥有一些对象的数组并根据数组及其动态大小(计数)填充列表?

【问题讨论】:

  • 您检查过 WWDC Combine 会话吗?还是 Session 226:通过 SwiftUI 获取数据? developer.apple.com/videos/play/wwdc2019/226 这就是你应该开始的地方。注意“真相之源”、@State、@Binding` 和其他所有内容。

标签: ios uikit tableview swiftui


【解决方案1】:

单元格被重复使用。 见Does the List in SwiftUI reuse cells similar to UITableView?

对于静态列表,限制为 10 个项目。 这与ViewBuilder 实现有关。

extension ViewBuilder {

    public static func buildBlock<C0, C1>(_ c0: C0, _ c1: C1) -> TupleView<(C0, C1)> where C0 : View, C1 : View
}

…

extension ViewBuilder {

    public static func buildBlock<C0, C1, C2, C3, C4, C5, C6, C7, C8, C9>(_ c0: C0, _ c1: C1, _ c2: C2, _ c3: C3, _ c4: C4, _ c5: C5, _ c6: C6, _ c7: C7, _ c8: C8, _ c9: C9) -> TupleView<(C0, C1, C2, C3, C4, C5, C6, C7, C8, C9)> where C0 : View, C1 : View, C2 : View, C3 : View, C4 : View, C5 : View, C6 : View, C7 : View, C8 : View, C9 : View
}

要使用数组,您可以使用此 API:


let array = [1,2,3,4]

let listView = List(array) { value in
    Text(value.description)
}

extension List {

extension List {

    /// Creates a List that computes its rows on demand from an underlying
    /// collection of identified data.
    @available(watchOS, unavailable)
    public init<Data, RowContent>(_ data: Data, selection: Binding<Selection>?, rowContent: @escaping (Data.Element.IdentifiedValue) -> RowContent) where Content == ForEach<Data, HStack<RowContent>>, Data : RandomAccessCollection, RowContent : View, Data.Element : Identifiable

…

【讨论】:

    【解决方案2】:

    动态视图通常由动态数据生成。因此,您应该考虑为重复视图使用数据结构,然后根据如下数据构建列表:

    struct Student: Identifiable {
        let name: String
        let id: Int
    }
    
    struct ContentView : View {
    
        // Could be `@State Var` instead
        let students = [
            Student(name: "AAAAA", id: 1),
            Student(name: "BBBBB", id: 2),
            Student(name: "CCCCC", id: 3), // Notice that trailing comma is not problem here? 
        ]
    
        var body: some View {
            List(students) { student in
                Text(student.name)
            }
        }
    }
    

    数组应包含Identifiable 对象(推荐)

    或者如果你不喜欢遵循Identifiable 协议,你可以像这样使用它:

    struct Book {
        let anyPropertyName: String
        let title: String
    }
    
    struct ContentView : View {
    
        // Could be `@State Var` instead
        let books = [
            Book(anyPropertyName: "AAAA", title: "1111"),
            Book(anyPropertyName: "BBBB", title: "2222"),
            Book(anyPropertyName: "CCCC", title: "3333")
        ]
    
        var body: some View {
            List(books.identified(by: \.anyPropertyName)) { book in
                Text(book.title)
            }
        }
    }
    

    请注意, dataSource 可以是@State var,它可以在任何@State var 更改时更新 UI。

    最后,虽然看起来不是重用,但实际上是! 10个静态项目的限制与重用无关。

    【讨论】:

    • 我更新了我的问题和答案以使其更清楚。感谢您的关注。
    • 好的,让我们专注于您对动态的定义。 books in your code has three elements. Are you trying to update the List` 当 books 中的某些/任何内容更新时?如果是这样,您是否考虑过使用@State?这个概念对 SwiftUI 来说非常关键。至于Identifiable,我想你想在struct 中声明一个UUID() 元素。
    • 你完全正确!但是书籍只是一个例子,与“列表”分开。为了您的担心,我在代码中添加了一些 cmets。再次感谢
    • 我有些不懂。以为这是“动态”的定义,但也许这就是您所说的“可重用”的意思。假设你有这个 books 数组和一个基于它的 SwiftUI 列表。在您的示例中,我希望该列表包含“AAAA”、“BBBB”和“CCCC”。然后呢?您是否尝试在另一个视图中使用此数组?如果是这样,使用 Apple 的术语,什么视图是“真理之源”?
    • 啊。也许现在我明白了。您是否在考虑 UITableView 的工作原理?可重复使用的细胞?如果是这样,你检查过这个问题吗? stackoverflow.com/questions/56655421/… 从它的声音来看,它“正常工作”。内存占用表明您不必担心。
    猜你喜欢
    • 2021-04-04
    • 2021-08-04
    • 1970-01-01
    • 1970-01-01
    • 2017-11-13
    • 2021-01-05
    • 2020-06-25
    • 2013-04-26
    • 2020-07-13
    相关资源
    最近更新 更多