我正在尝试使用@Published
聆听字典中元素的变化。
我有一个字典,包含玩家分数列表,按玩家id索引。它看起来像这样:
class PlayersScore: ObservableObject {
@Published var scores: [String: PlayerScore] = [:];
}
这个字典是通过一个名为Api
的类的共享实例的scores
属性公开的。
class Api: NSObject {
static var shared = Api()
@Published public var scores = PlayersScore()
func updatePlayerScore(playerId: String, score: PlayerScore) {
this.scores.scores[playerId] = score
}
}
有时候,玩家的分数会被更新。
我有一个专门用于播放器的视图,看起来像这样:
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
作为一个可观察类,因此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)")
}
}
注意:这里只是一个草图编码,所以可能是打字错误