gpt4 book ai didi

view - SwiftUI 中的数据流与@EnvironmentObject

转载 作者:行者123 更新时间:2023-12-01 01:40:54 24 4
gpt4 key购买 nike

我的应用程序中有三个 View 。第一个显示游戏列表。第二个是每场比赛的球员名单。第三个有每个玩家的得分列表。所以结构看起来像这样:

struct GameView: View {

@environmentObject var model: Model

var body: some View {
NavigationView {
List(model.games) {game in
NavigationLink(destination: PlayerView(game: game)) {
// Some View
}
}
}
}
}

struct PlayerView: View {

@environmentObject var model: Model
var game Game
var gameIndex: Int {
model.games.firstIndex() {$0 == game}!
}

var body: some View {
TextField("Game", $model.games[gameIndex].title)
List(game.players) {player in
NavigationLink(destination: ScoreView(player: player, gameIndex: gameIndex)) {
// Some View
}
}
}
}

struct ScoreView: View {

@environmentObject var model: Model
var player: Player
var gameIndex: Int

var playerIndex: Int {
model.games[gameIndex].players.firstIndex() { $0 == player }!
}


var body: some View {
TextField("Player", $model.games[gameIndex].players[playerIndex].name)
List(player.scores) {score in
// Some View
}
}
}

我的问题是:对于深入层次结构的每个 View ,我必须一直返回到我的 environmentObject 并通过带有索引的模型数组获取路径,我必须通过每个 View 。如果我更改 TextField 值(仅作为应用程序中每个数据更改的示例)并且如果我在 NavigationView 中前后移动,我希望更新每个 View 。我敢肯定,有一些糟糕的构造错误,但我没有得到正确的答案。

最佳答案

对于像你正在做的事情,我会使用 ObservedObject这对于将特定数据从一个 View 传递到另一个 View 很有用——尤其是当对象中的某些属性可能会更改并且需要对其使用react时。

您的输入很有意义,但我认为您应该只能使用输入而不是访问 model EnvironmentObject .例如,在 PlayerView代码,你可以做 game.title而不是 $model.games[gameIndex].title .问题是,正如您的代码一样,对游戏标题的更改将不会反射(reflect)这就是 ObservedObject进来。喜欢EnvironmentObject , ObservedObject s 将告诉 SwiftUI 在对象更新时更新 View 。两个EnvironmentObjectObservedObject要求类符合相同的ObservableObject协议(protocol)(以前称为 BindableObject )。

您要做的主要更改是添加 ObservedObject View 输入的属性包装器,如 gameplayer .您可能还需要添加 ObservableObject符合 GamePlayer如果你还没有上课。

this article解释了 SwiftUI 中不同类型的数据绑定(bind),包括 ObservedObject .

编辑 - 未显示更改

一个可能导致更改不显示的“陷阱”是每个对象都需要发出 ObjectWillChange事件不仅在其自身的值(value)观发生变化时发生,而且在其任何 child 的值(value)观发生变化时发生。如果有 ObservableObject 的数组,这将更加复杂。 s 参与。

这是我在这种情况下使用的代码:

// an array of cancelables because we need to subscribe to every object in the players array.
var playerCans: [Cancellable]?

@Published var players: [Player] = [Player(), Player()] {
didSet {
// necessary because if the array gets set to something new,
// we want to notify of changes to the new array, not the old one
setupCans()
}
}

init() {
setupCans()
}

func setupCans() {
// Not sure if canceling is necessary, but doing it just in case
self.playerCans?.forEach({ (can) in
can.cancel()
})
self.playerCans = players.map { (player) in
return player.objectWillChange.sink {
self.objectWillChange.send()
}
}
}

关于view - SwiftUI 中的数据流与@EnvironmentObject,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57620192/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com