0

In SwiftUI, we have List to represent reusable items. Just like UITableView in UIKit.

Static lists builds like this:

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

But seems like it's not reusable at all

How can I have an array of some objects and fill the list based on the array and its dynamic size (count)?

Mojtaba Hosseini
  • 95,414
  • 31
  • 268
  • 278
  • 1
    Have you checked the WWDC `Combine` sessions? Or Session 226: Data Flor Through SwiftUI? https://developer.apple.com/videos/play/wwdc2019/226/ That's where you should start. Pay attention to "Source of Truth", `@State`, @Binding` and everything else. –  Jun 18 '19 at 18:27

2 Answers2

0

Cell are reused. See Does the List in SwiftUI reuse cells similar to UITableView?

For static Lists the limit are 10 Items. This has to do with the ViewBuilder implementation.

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
}

To use an array you can use this 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

…
Ugo Arangino
  • 2,802
  • 1
  • 18
  • 19
-1

Dynamic views usually generated from dynamic data. So you should consider using a data structure for your repeating views, then build the list based on data like this:

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)
        }
    }
}

Array should contain Identifiable objects (Recommended)

or if you not prefer to conform to Identifiable protocol you can use it like this:

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)
        }
    }
}

Note that dataSource can be @State var and it gives the ability to update the UI whenever any @State var changes.

Lastly, although it seems like it's not reusing, but actually it is! The limit of 10 static items has nothing to do with reusing.

Mojtaba Hosseini
  • 95,414
  • 31
  • 268
  • 278
  • I updated my question and answer a bit to make it more clear. Thanks for you attention. – Mojtaba Hosseini Jun 18 '19 at 18:38
  • Okay, let's focus on your definition of *dynamic*. `books in your code has three elements. Are you trying to update the `List` when something/anything is updated in `books`? If so, have you looked into using `@State`? This concept is very critical to SwiftUI. As for `Identifiable`, I'm thinking you want to declare a `UUID()` element in your `struct`. –  Jun 18 '19 at 19:17
  • You are absolutely right! But books is just an example and separated from the ‘List’. For the sake of your concerns I added some comments to the code. Thanks again – Mojtaba Hosseini Jun 18 '19 at 19:19
  • I'm not understanding something. Thought it was the definition of "dynamic", but maybe it's what you mean by "reusable" then. Let's say you have this `books` array and a SwiftUI list based on it. I your example I'd expect the list to contain "AAAA", "BBBB', and "CCCC". Then what? Are you trying to use this array in another view? And if so, to use Apple's terms, what view is the "Source of Truth"? –  Jun 18 '19 at 20:31
  • AH. Maybe *now* I get it. Are you thinking in terms of how a `UITableView` works? Reusable cells? IF so, have you checked out this question? https://stackoverflow.com/questions/56655421/does-the-list-in-swiftui-reuse-cells-similar-to-uitableview From the sounds of it, it "just works". The memory footprint indicates that you shouldn't worry about that. –  Jun 18 '19 at 20:33
  • Yes I meant reusing views the way UITableView does. And yes, as I researched within memory graph and UIDebugger and etc, it turns out that **`List` view's subViews** are reusable. – Mojtaba Hosseini Jun 18 '19 at 20:37
  • what about different rowView in one **List** ?) – iTux Aug 08 '19 at 21:00