CS193视图不随模型更新(MVVM)

3

我一直在跟随斯坦福大学的SwiftUI课程,现在我已经到了一个地步,我可以百分之百确定我的代码基本上与我所跟随的代码相同,但它却不能正常工作。我一直在尝试调试它,但由于某些我不理解的原因,视图没有更新。

视图模型:

class CardModel: ObservableObject
{
    // view model
    static var items = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T",]
    static var count = 3
    
    static func createMemoryGame() -> MemoryGame<String>
    {
        MemoryGame<String>(numberOfPairsOfCards: CardModel.count, createCardContent:
        {
            pairIndex in
            CardModel.items[pairIndex]
        })
    }
    
    @Published private var model: MemoryGame<String> = CardModel.createMemoryGame()
    
    var cards: Array<MemoryGame<String>.Card>
    {
        return model.cards
    }
    
    // MARKS: - Intent(s)
    
    func choose(_ card: MemoryGame<String>.Card)
    {
        print("debug func choose in cardmodel")
        model.choose(card)
    }
    
}

视图:

struct ContentView: View{
    @ObservedObject var viewModel: CardModel
    
    var body: some View
    {
        VStack
        {
            LazyVGrid(columns: [GridItem(.adaptive(minimum: 75))])
            {
                ForEach(viewModel.cards)
                {
                    card in
                    CardView(card: card).aspectRatio(2/3, contentMode: .fit)
                        .onTapGesture {
                            print("\(card.isFaceUp)")
                            viewModel.choose(card)
                            print("\(card.isFaceUp)")
                        }
                }
            }
            Spacer()
            .foregroundColor(.red)
        }
        .padding(.horizontal)
        .font(.largeTitle)
    }
}

模型:

struct MemoryGame<CardContent>
{
    private(set) var cards: Array<Card>
    
    mutating func choose(_ card: Card)
    {
        let chosenIndex = index(of: card)
        cards[chosenIndex].isFaceUp = !cards[chosenIndex].isFaceUp
        print("debug func choose in memorygame")
    }
    
    func index(of card: Card) -> Int
    {
        for index in 0..<cards.count
        {
            if cards[index].id == card.id
            {
                print("debug func index")
                return index
            }
        }
        return 0
    }

当我取消所有调试注释时,输出为:

-真 -卡片模型中选择调试功能 -索引调试函数 -在记忆游戏中选择调试功能 -真

https://www.youtube.com/watch?v=oWZOFSYS5GE 这是我卡住的视频,直到32:48,所有代码都通过了相同的调试测试。


添加相关代码,而不是屏幕截图 - timbre timbre
1
请尽可能添加简单易懂的可运行代码,以展示您遇到的问题。 - dtm
他们直到32:48之后才能获取视图模型以发布更改。 - Paulw11
1个回答

2
不幸的是,斯坦福大学的CS193课程完全错误地教授了SwiftUI。我建议使用苹果公司的示例和WWDC视频来学习正确的结构。MMVM是一个很大的错误,View结构体和property wrapper就足够了。原因是View结构体已经存储了SwiftUI所需的数据,并对其进行差异化处理,然后代表我们创建UIView / NSView。此外,像@State和@Binding这样的属性包装器使高效的结构体行为像一个对象。所以你的视图模型对象就在那里。如果您同时使用实际对象,则会遇到SwiftUI旨在消除的一致性错误。
要修复您分享的代码,请尝试以下内容:
    class CardStore: ObservableObject
    {
        @Published var cards: [Card] = []
    
        static var shared = CardStore()
    
        static var preview = CardStore(preview: true)
    
        init(preview: Bool = false) {
            // create initial cards array depending on preview or not
        }

        // other funcs that can work on Cards, usually looking up by their ID (from Identifiable).

@main
struct CardGame: App {
    let store = CardStore.shared

    var body: some Scene { 
        WindowGroup {
            ContentView()
                .environmentObject(store)
        }
    }
}

struct ContentView: View {
    @EnvironmentObject var store: CardStore

   var body: some View {
       ForEach($card in store.cards) { $card in
           CardView(card: $card)
       }
   }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView().environmentObject(CardStore.preview)
    }
}

struct CardView: View {
    @Binding var card: Card

    var body: some View {
        FaceUpView(isFaceUp: $card.isFaceUp)
    }
}

struct FaceUpView {
    @Binding var isFaceUp: Bool

    var body: some View {
        // here you have write access to isFaceUp, in the card, from the store.
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接