swiftuilazyvgridswiftui-foreach

Using Grid container for an array of objects


In my model, I create an array of objects:

let myObjects = [ theObject(name: "first", ...),
                  theObject(name: "second", ...), etc.

I want to use the SwiftUI Grid container view to display the objects' contents in a 2-column layout. But the GridRow structure is accessing the array more than once per pass, making a ForEach tricky:

GridRow {
    Text(myObjects[i].name)
    Text(myObjects[i+1].name)
}
GridRow {
    ... etc

I'm not sure of the best way to iterate through these objects. Here are three ideas:

1. Don't use Grid

I could use a lazy method (like LazyVGrid), which would lay the objects out as they are enumerated one-by-one. But I like the control and finesse of using this new (iOS 16) Grid container.

2. Change the Model

The model could carry both information in each object:

let myObjects = [ theObject(firstName: "first", secondName: "second", ...),
                  theObject(firstName: "third", secondName: "fourth", ...), etc.

But yuck, that just smells. And what if I decide to have three columns?

3. Carry a pointer

Use an integer to point to the elements in the array:

ForEach(0...((myObjects.count - 1) / 2), id: \.self) { i in
    GridRow {
        Text(myObjects[i*2].name)
        if (i*2) < myObjects.count - 1 { // to guard against an odd number of elements
            Text(myObjects[(i*2) + 1].name)
        }
    }
}

This also feels painful, and not adaptive if I change the number of columns.

What technique am I not thinking of? Would you consider any of these acceptable?


Solution

  • I ended up using a LazyVGrid for this.