程序问答   发布时间:2022-06-01  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了SwiftUI ChildView 未在状态更改时重新计算大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

如何解决SwiftUI ChildView 未在状态更改时重新计算?

开发过程中遇到SwiftUI ChildView 未在状态更改时重新计算的问题如何解决?下面主要结合日常开发的经验,给出你关于SwiftUI ChildView 未在状态更改时重新计算的解决方法建议,希望对你解决SwiftUI ChildView 未在状态更改时重新计算有所启发或帮助;

所以这很可能是一个 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)
  }
}



解决方法

这对我来说是一个愚蠢的错误。问题实际上是 Equatable 的不成熟实现,从 Swift 4.1+ 开始实际上不再需要它(Hashable 也是如此)。我最初添加它是为了确保我可以比较 Cards(需要 index(of:) 方法),但是,由于我只是检查比较 id 的,它与 SwiftUI 的内部比较算法用于重绘。 SwiftUI 也在使用我的 Equatable 实现并认为卡实际上并没有改变!

大佬总结

以上是大佬教程为你收集整理的SwiftUI ChildView 未在状态更改时重新计算全部内容,希望文章能够帮你解决SwiftUI ChildView 未在状态更改时重新计算所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。
标签: