Swift观察动态字典

Swift Observe dynamic dictionary

我正在尝试使用 @Published 监听字典中元素的变化。

我有一本字典,包含玩家分数列表,由玩家 ID 索引。 它看起来像这样:

class PlayersScore: ObservableObject {
    @Published var scores: [String: PlayerScore] = [:];
}

此字典通过名为 Api 的 class 共享实例的 属性 scores 公开。

class Api: NSObject {
   static var shared = Api()
   @Published public var scores = PlayersScore()

   func updatePlayerScore(playerId: String, score: PlayerScore) {
       this.scores.scores[playerId] = score
   }
}

有时,玩家的分数会更新。

我有一个专用于 Player 的视图,如下所示:

struct PlayerView: View {
   var player: Player
   @ObservedObject private var scores = Api.shared.scores

   var body: some View {
       HStack {
           Text(player.name)
           Text("Latest score: \(scores.scores[player.id] ?? "not found")")
       }
   }
}

当玩家的分数更新时,我的视图会重新渲染。
我的问题是......当玩家分数更新时,所有玩家的视图都会重新呈现,因为他们都会对主字典的变化做出反应。

所以,我想在他的相应视图中订阅特定玩家得分的变化,因此只有适当的视图在必要时重新呈现。

订阅或访问时玩家分数可能尚未初始化(即 scores.scores[player.id] 可能尚不存在)。

知道如何实现吗?

谢谢!

这里有一个可行的方法——让PlayerScore成为可观察的class,这样PlayersScore只会在新玩家加入时更新,并且由于观察到特定的PlayerScore明确只对应视图将根据 value 更改进行更新。

class PlayerScore: ObservableObject {
  var id: String  // say back ref to user

  @Published var value: Int
  // ... other published properties
}

struct PlayerView: View {
   var player: Player
   @ObservedObject private var scores = Api.shared.scores

   var body: some View {
       HStack {
           Text(player.name)
           if let score = scores.scores[player.id] {
              PlayerScoreView(playerScore: score)
           } else {
              Text("No scores")
           }
       }
   }
}

struct PlayerScoreView: View {
  @ObservedObject var playerScore: PlayerScore

  var body: some View {
     Text("Latest score: \(playerScore.value)")
  }
}

注意:这只是此处编码的草图,因此可能有错别字