1

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.

2
  • 1
    ForEach(itemsTemp , id: \.self), You are saying each value in itemsTemp is unique, but you also have duplicates. Commented Feb 27, 2021 at 8:48
  • @TusharSharma I updated my question . would you check please now. Commented Feb 27, 2021 at 9:10

2 Answers 2

7

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
Sign up to request clarification or add additional context in comments.

8 Comments

I guess id parameter is not required in forEach if you use Identifiable protocol.
Sorry for my wrong. I just updated my question . would you check it please.
@TusharSharma yes.
@NazmulHasan I added a second approach. Does this help?
@RajaKishan it's help but sometime LazyVGrid item overlap one by another
|
1

try with a model:

enter image description here

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


class Model: ObservableObject {
    var items: [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")
    ]
    @Published var itemsSuffled: [Item] = []
    
    init() {
        shuffle()
    }
    
    func shuffle() {
        itemsSuffled = items.shuffled()
    }
}

struct ContentView: View {
    
    @Namespace private var namespace
    @ObservedObject private var model: Model = Model()
    
    var body: some View {
        
        VStack {
            LazyVGrid(columns: [GridItem(),GridItem()],spacing: 16) {
                ForEach(model.itemsSuffled) { item in
                        VStack {
                            Text(item.name).id(UUID())
                                  .matchedGeometryEffect(id:UUID(), in: namespace, isSource: true)
                                  .onTapGesture{
                                           print(" tapped!")
                                    }
                                }.matchedGeometryEffect(id: "container\(UUID())", in: namespace)
                             }
            }
            Button(action: {
                model.shuffle()
            }, label: {
                Text("new shuffle")
            })
        }
        
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.