Search code examples
swiftforeachswiftuilazyvgrid

How to allow ForEach layout item to show duplicate item from array in SwiftUI?


I am working with on multiple choose answer quiz app.

var itemsTemp = ["ant","bat", "bear", "bee", "bird", "butterfly", "camel", "cat", "cheetah","chick", "chicken"]

Updated Here is example of my quiz app.

  let answerIndex = Int.random(in: 0...3) // for correct answer
  itemsTemp!.shuffle() // to multiple choose option change. 

here is the error:

Thread 1: Fatal error: each layout item may only occur once

Bellow code crashing

LazyVGrid(columns: [GridItem(),GridItem()],spacing: 16) {
       ForEach(itemsTemp) { item in
            VStack {
                    Text(item).id(UUID())
                      .matchedGeometryEffect(id:UUID(), in: namespace, isSource: !show)
                      .onTapGesture{
                               print(" tapped!")
                        }
                    }.matchedGeometryEffect(id: "container\(UUID())", in: namespace)
                 }
              }

it's a quiz app so multiple choose option to select correct answer. array item will be occur in for each loop multiple time.

So need to each layout item multiple occur.


Solution

  • For the unique identifier. Use a model array instead of a string array.

    First, create a model.

    struct Item: Identifiable {
        var id = UUID()
        var name: String
    }
    

    then, your array is

    var itemsTemp: [Item] = [
        .init(name: "ant"),
        .init(name: "bat"),
        .init(name: "ant"),
        .init(name: "bear"),
        .init(name: "bee"),
        .init(name: "ant"),
        .init(name: "butterfly"),
        .init(name: "bear")
    ]
    

    Now, your loop is

    //Other Code
    ForEach(itemsTemp, id:\.id) { item in
        //Other Code
    }
    //Other Code
    


    The second approach is to use .indices.

    //Other Code
    ForEach(itemsTemp.indices) { index in
        let item = temsTemp[index]
        //Other Code
    }
    //Other Code