[英]SwiftUI not updating ObservedObject in child-view
所以我嘗試從斯坦福 CS193p 學習 SwiftUI。 這很好用,但是,我無法理解為什么這不起作用。 我和老師的觀點完全一樣:
struct ContentView: View {
@ObservedObject var viewModel: EmojiMemoryGame
var body: some View {
HStack {
ForEach(self.viewModel.cards) { card in
CardView(card: card).onTapGesture {
self.viewModel.chooseCard(card: card)
}
}
.aspectRatio(2/3, contentMode: .fit)
}
.foregroundColor(.orange)
.padding()
.font(viewModel.numberOfPairsOfCards >= 5 ? .callout : .largeTitle)
}
}
struct CardView: View {
var card: MemoryGame<String>.Card
var body: some View {
VStack {
ZStack {
if card.isFaceUp {
RoundedRectangle(cornerRadius: 10.0).fill(Color.white)
RoundedRectangle(cornerRadius: 10.0).stroke(lineWidth: 3)
Text(card.content)
} else {
RoundedRectangle(cornerRadius: 10.0).fill(Color.orange)
}
}
}
}
}
問題是這不會更新視圖,就好像來自 model 的已發布信息沒有傳遞到層次結構中一樣。 我知道它有效,因為如果我將代碼更改為:
struct ContentView: View {
@ObservedObject var viewModel: EmojiMemoryGame
var body: some View {
HStack {
ForEach(self.viewModel.cards) { card in
ZStack {
if card.isFaceUp {
RoundedRectangle(cornerRadius: 10.0).fill(Color.white)
RoundedRectangle(cornerRadius: 10.0).stroke(lineWidth: 3)
Text(card.content)
} else {
RoundedRectangle(cornerRadius: 10.0).fill(Color.orange)
}
}
.onTapGesture {
self.viewModel.chooseCard(card: card)
}
}
.aspectRatio(2/3, contentMode: .fit)
}
.foregroundColor(.orange)
.padding()
.font(viewModel.numberOfPairsOfCards >= 5 ? .callout : .largeTitle)
}
}
一切正常。 非常感謝所有幫助!
class EmojiMemoryGame: ObservableObject {
@Published private var game: MemoryGame<String> = EmojiMemoryGame.createMemoryGame()
static private func createMemoryGame() -> MemoryGame<String> {
let emojis = ["🎃", "👻", "🕷", "😈", "🦇"]
return MemoryGame(numberOfPairsOfCards: Int.random(in: 2...5)) { emojis[$0] }
}
//MARK: - Access to the Model
var cards: Array<MemoryGame<String>.Card> {
game.cards
}
var numberOfPairsOfCards: Int {
game.cards.count / 2
}
//MARK: - Intents
func chooseCard(card: MemoryGame<String>.Card) {
game.choose(card)
}
}
struct MemoryGame<CardContent> {
var cards: Array<Card>
mutating func choose(_ card: Card) {
if let indexOfCard = cards.firstIndex(of: card) {
cards[indexOfCard].isFaceUp.toggle()
}
}
init(numberOfPairsOfCards: Int, cardContentFactory: (Int) -> CardContent) {
cards = Array<Card>()
for pairIndex in 0..<numberOfPairsOfCards {
let content = cardContentFactory(pairIndex);
cards.append(Card(content: content, id: pairIndex * 2))
cards.append(Card(content: content, id: pairIndex * 2 + 1))
}
cards.shuffle()
}
struct Card: Identifiable, Equatable {
static func == (lhs: MemoryGame<CardContent>.Card, rhs: MemoryGame<CardContent>.Card) -> Bool {
lhs.id == rhs.id
}
var isFaceUp = true
var isMatched = false
var content: CardContent
var id: Int
}
}
Card 結構中相等運算符的實現僅比較 id。 CardView 沒有更新,因為 SwiftUI 推斷卡沒有改變。
請注意,您可能還想檢查 card 的其他屬性(CardContent 需要符合 Equatable)。
struct Card: Identifiable, Equatable {
static func == (lhs: MemoryGame<CardContent>.Card, rhs: MemoryGame<CardContent>.Card) -> Bool {
return lhs.id == rhs.id && lhs.isFaceUp == rhs.isFaceUp
}
var isFaceUp = true
var isMatched = false
var content: CardContent
var id: Int
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.