swiftuics193plazyvgrid

Preview crashed after added LazyVGrid


I am learning Stanford CS193p, and everything went so well till switching LazyVGrid with HStack.

I checked my code with the one professor made, they are the same. But the confusing part of my code is that, when my emojiCount = 4, preview worked well, I can use LazyVGrid, however when I changed emojiCount value more than 4, like 5 or 24, it would crash right away.

The crash info is this:

Diagnostics

And here is my code:

import SwiftUI

struct ContentView: View {
    var emojis = ["🚔", "🚂", "🚀", "🚘", "🚂", "🚀", "🚘", "🚂", "🚀", "🚘", "🚂", "🚀", "🚘", "🚂", "🚀", "🚀", "🚘", "🚂", "🚀", "🚀", "🚘", "🚂", "🚀", "🚀", "🚘"]
   @State var emojiCount = 4
    
    var body: some View {
        VStack {
            LazyVGrid(columns:[GridItem(),GridItem(),GridItem()]) {
                ForEach(emojis[0..<emojiCount], id: \.self) { emoji in
                    CardView(content: emoji)
                }
            }
            .foregroundColor(.red)
            Spacer()
            HStack {
                remove
                Spacer()
                add
            }
            .font(.largeTitle)
            .padding(.horizontal)
        }
        .padding(.horizontal)
    }
    
    var remove: some View {
        Button {
            if emojiCount > 2 {
                emojiCount -= 1
            }
        } label: {
            Image(systemName:"minus.circle")
            }
    }
    
    var add: some View {
        Button {
            if emojiCount < emojis.count {
                emojiCount += 1
            }
        } label: {
            Image(systemName:"plus.circle")
            }
    }
}


struct CardView: View {
    var content: String
    @State var isFaceUp: Bool = true
    
    var body: some View {
        ZStack {
            let shape = RoundedRectangle(cornerRadius: 20)
            if isFaceUp {
                shape.fill().foregroundColor(.white)
                shape.stroke(lineWidth: 3)
                Text(content).font(.largeTitle)
            } else {
                shape.fill()
            }
        }
        .onTapGesture {
            isFaceUp = !isFaceUp
        }
    }
}


I tried to figure out the whole night, but I still don't know what's wrong with my code. Thank you so much!


Solution

  • Run the code in the simulator and you will see the error

    Fatal error: each layout item may only occur once

    This leads to the emojis. You have a lot of them but only 4 different types. In a loop where the items are referenced by \.self you are responsible for making sure that the items are unique.