I was following along with this lecture when I ran into some problems with my Observed Object updating. I have an @ObservedObject called EmojiMemoryGame with a published MemoryGame<String> variable called model. 'MemoryGame' is a struct that stores an array of cards, which each have a Bool variable that stores whether they are face up or not.
My ContentView is a View that shows each card in a grid on screen. When the user taps the card, viewModel.choose(card) toggles the isFaceUp variable of the card; the problem is that this does not cause the card to flip over on screen. This is my code in ContentView.swift:
struct ContentView: View {
    @ObservedObject var viewModel: EmojiMemoryGame
    
    var body: some View {
        ScrollView {
            LazyVGrid(columns: [GridItem(.adaptive(minimum: 89))]) {
                ForEach(viewModel.cards) { card in
                    CardView(card: card)
                        .aspectRatio(2/3, contentMode: .fit)
                        .onTapGesture {
                            viewModel.choose(card)
                        }
                }
            }
        }
        .foregroundColor(.red)
        .padding(.horizontal)
    }
}
struct CardView: View {
    let card: MemoryGame<String>.Card
    
    var body: some View {
        ZStack {
            let shape = RoundedRectangle(cornerRadius: 20)
            
            if card.isFaceUp {
                shape
                    .fill()
                    .foregroundColor(.white)
                shape
                    .strokeBorder(lineWidth: 3)
                Text(card.content)
                    .font(.largeTitle)
            } else {
                shape
                    .fill()
            }
        }
    }
}
However, the code works as expected if I instead just copy/paste the code from CardView directly into the body of ContentView (see below), so I'm not really sure what is going on here.
struct ContentView: View {
    @ObservedObject var viewModel: EmojiMemoryGame
    
    var body: some View {
        ScrollView {
            LazyVGrid(columns: [GridItem(.adaptive(minimum: 89))]) {
                ForEach(viewModel.cards) { card in
                    ZStack {
                        let shape = RoundedRectangle(cornerRadius: 20)
                        
                        if card.isFaceUp {
                            shape
                                .fill()
                                .foregroundColor(.white)
                            shape
                                .strokeBorder(lineWidth: 3)
                            Text(card.content)
                                .font(.largeTitle)
                        } else {
                            shape
                                .fill()
                        }
                    }
                    .aspectRatio(2/3, contentMode: .fit)
                    .onTapGesture {
                        viewModel.choose(card)
                    }
                }
            }
        }
        .foregroundColor(.red)
        .padding(.horizontal)
    }
}
Edit: Here is my EmojiMemoryGame.swift:
class EmojiMemoryGame: ObservableObject {
    static let emojis = ["", "", "️", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""]
    
    static func createMemoryGame() -> MemoryGame<String> {
        MemoryGame<String>(numberOfPairsOfCards: 4) { pairIndex in
            emojis[pairIndex]
        }
    }
    @Published var model: MemoryGame<String> = createMemoryGame()
    var cards: Array<MemoryGame<String>.Card> {
        return model.cards
    }
    
    func choose(_ card: MemoryGame<String>.Card) {
        model.choose(card)
    }
}
and MemoryGame.swift:
struct MemoryGame<CardContent> where CardContent: Equatable {
    
    struct Card: Identifiable, Equatable {
        var isFaceUp: Bool = false
        var isMatched: Bool = false
        var content: CardContent
        
        var id: Int
        
        static func == (lhs: MemoryGame<CardContent>.Card, rhs: MemoryGame<CardContent>.Card) -> Bool {
            lhs.id == rhs.id
        }
        
    }
    
    private(set) var cards: Array<Card>
        
    init(numberOfPairsOfCards: Int, createCardContent: (Int) -> CardContent) {
        cards = Array<Card>()
        // add numberOfPairsOfCards * 2 cards to cards array
        for pairIndex in 0..<numberOfPairsOfCards {
            let content: CardContent = createCardContent(pairIndex)
            cards.append(Card(content: content, id: pairIndex*2))
            cards.append(Card(content: content, id: pairIndex*2 + 1))
        }
    }
    
    mutating func choose(_ card: Card) {
        let chosenIndex = cards.firstIndex(of: card)
        cards[chosenIndex!].isFaceUp.toggle()
    }
    
}