【发布时间】:2021-02-28 05:07:13
【问题描述】:
所以这很可能是一个新手 SwiftUI 问题,我有一个父视图,它采用 @ObservedObject(例如 viewModel),视图模型似乎正确地将模型中的更改发布到 CollectionView,并且视图正确地重新计算正文.但是,子视图的 (EmojiCell) 正文似乎没有重新计算?以下是相关代码,感谢任何见解。
如果我将 Card 更改为 ObservableClass 并将其 isFaceUp 设置为 @Published ,我可以让它工作,但这显然不是正确的解决方案!
struct CollectionView: View {
@ObservedObject var viewModel: EmojiMemoryGameViewModel
init(viewModel: EmojiMemoryGameViewModel) {
self.viewModel = viewModel
}
var body: some View {
// This is called on tap as expected so the viewModel is indeed
// correctly notifying the view of it's change, the body is
// recalculated, BUT EmojiCell's body doesn't get called!
print("CollectionView recalc")
return HStack {
ForEach(viewModel.cards) { card in
// This doesn't
EmojiCell(card: card).onTapGesture {
viewModel.choose(card: card)
}
// This works!
// return ZStack {
// if card.isFaceUp {
// RoundedRectangle(cornerRadius: 10)
// .fill(Color.white)
// RoundedRectangle(cornerRadius: 10)
// .stroke(lineWidth: 3)
// Text(card.content)
// }
// else {
// RoundedRectangle(cornerRadius: 10).fill()
// }
// }
// .onTapGesture {
// self.viewModel.choose(card: card)
// }
}
}
.padding()
.foregroundColor(.orange)
.font(.largeTitle)
}
}
typealias EmojiCard = MemoryGame<String>.Card
struct EmojiCell: View {
let card: EmojiCard
var body: some View {
print("Cell recalc")
return ZStack {
if card.isFaceUp {
RoundedRectangle(cornerRadius: 10)
.fill(Color.white)
RoundedRectangle(cornerRadius: 10)
.stroke(lineWidth: 3)
Text(card.content)
}
else {
RoundedRectangle(cornerRadius: 10).fill()
}
}
}
}
// Other relevant code
struct Card: Identifiable, Hashable {
var id: Int
var isFaceUp = true
var isMatched = false
var content: CardContent
func hash(into hasher: inout Hasher) {
hasher.combine(id)
}
}
extension MemoryGame.Card: Equatable {
static func == (lhs: MemoryGame<CardContent>.Card, rhs: MemoryGame<CardContent>.Card) -> Bool {
return lhs.id == rhs.id
}
}
class EmojiMemoryGameViewModel: ObservableObject {
@Published private var model: MemoryGame<String> = EmojiMemoryGameViewModel.createMemoryGame()
static func createMemoryGame() -> MemoryGame<String> {
let listOfCards = ["????", "????", "????"]
return MemoryGame(numberOfPairsOfCards: listOfCards.count) { index in
return listOfCards[index]
}
}
var cards: [MemoryGame<String>.Card] {
model.cards
}
func choose(card: MemoryGame<String>.Card) {
model.choose(card)
}
}
【问题讨论】:
-
如果没有Minimal Reproducible Example,就不可能帮助您编写代码。看来您对
ObservableObjects的细节不熟悉,可能会发生很多事情@Published private var不应该是private,这就是SwiftUI 应该引用的内容,将listOfCards放在那里,而不是引用一个方法。在EmojiCellEmojiCard应该是ObservableObject它永远不会被告知重新加载。看Apple SwiftUI tutorials -
感谢您抽出宝贵时间回复,我发现我的代码有问题,实际上不是您指出的任何点(我认为这不是有效点)。