Retrieve specific element from dynamic array in SwiftUI

Viewed 376

Right, I'm new to swift(ui) and have been experimenting - my current issue is to do with a basic card app. I have generated a deck of card objects (in this case 10 items) and first displayed them all in a stack using a ForEach loop - no problem there. I then went on to pull out one card from the array to display on it's own nd this is where everything comes to a crashing halt. I suspect it's something simple and obvious but how do I get a single card from my deck for display?

struct Card: Identifiable, Equatable{
let id = UUID()
var factor1: Int = 0
var factor2: Int = 0
var product: Int = 0
var possibleAnswers: [Int] = []
}
struct CardView: View{
let card: Card
var body: some View{
    VStack {
    VStack { // Actual Card
        Spacer()
            Text("\(card.factor1) X \(card.factor2)")
                .font(.title)
                .foregroundColor(.black)
               // .bold()
                .multilineTextAlignment(.center)
                .padding(.horizontal)
                Spacer()
    }
    .padding()
    .frame(width: 300, height: 200)
    .background(
      Rectangle()
           .foregroundColor(cardColor(of: card))
    )
    
        HStack {
            Spacer()
            ForEach(card.possibleAnswers, id:\.self) { answer in
                Text("\(answer)")
                    .foregroundColor(.black)
                    .frame(width: 75, height: 50)
                    .background(
                      Rectangle()
                           .foregroundColor(cardColor(of: card))
                    )
                Spacer()
            }
        }
        .padding()

    }
}

func cardColor(of card: Card) -> Color {
    return Color(red:228/255, green: 229/255, blue: 229/255)
}
}

class Deck: ObservableObject {
@Published var numberCards = 10
@Published var cards = [Card]()

func buildDeck() {
    cards.removeAll()
    let cardCount = 1...self.numberCards
    for _ in cardCount {
                // Set up new card
                var myCard = Card()
                myCard.factor1 = .random(in: 1...12)
                myCard.factor2 = .random(in: 1...12)
                myCard.product = myCard.factor1 * myCard.factor2
                myCard.possibleAnswers.append(myCard.product)
                for _ in 0...2{
                    myCard.possibleAnswers.append(Int.random(in: 1..<145))
                }
                myCard.possibleAnswers.shuffle()
                // add card to the deck
                self.cards.append(myCard)
    }
}

var count: Int {
    return cards.count
}
}


struct ContentView: View {
@StateObject var deck = Deck()
var body: some View {
    VStack {
        Button(action: {
                deck.buildDeck()
        }) { // button text
            Text("Click to add card. Current Number of cards in deck: \(deck.count)")
        }
        Spacer()
    ZStack {
//             ForEach(deck.cards) { card in
        if let card = deck.cards[0] {
           CardView(card: card)
        }
//           }
    }
        Spacer()
    }
}
}
1 Answers

From the code provided, it looks like this error was caused by accessing an index that an array doesn't even have in the first place.

In this case, you're accessing the first element of cards while in buildDeck function you removed all the elements which may be the cause of the error while it's:

let card = deck.cards[0]
CardView(card: card)

You can try to use if let to make sure the element is present before accessing it.

if let card = deck.cards.first {
   CardView(card: card)
}
Related