我目前正在编写我的第一个 SwiftData 应用程序。
我创建了两个模型:
玩家.swift:
@Model
final class Player {
@Relationship(inverse: \Game.players) var games: [Game]
var name: String
var id: UUID
init(games: [Game] = [], name: String = "", id: UUID = UUID()) {
self.games = games
self.name = name
self.id = id
}
}
游戏.swift:
@Model
final class Game {
@Relationship var players: [Player]
init(players: [Player] = []) {
self.players = players
}
}
如果我使用players变量显示游戏的玩家,顺序总是相同的,但我不知道为什么以及排序描述符是什么。如果想使用.move重新排列顺序,但不起作用。玩家立即向后跳。如果我使用 .append(),播放器总是附加在相同的位置,具体取决于我使用的位置。例如,如果我添加
Player(games: [], name: "Frank", id: UUID())
,它始终附加在第二个位置,而 Player(games: [], name: "Sean", id: UUID())
始终附加在第四个位置。
GameView.swift:
struct GameView: View {
@Bindable var game = Game()
var body: some View {
NavigationStack {
Form {
Section("Spieler") {
ForEach(game.players) { player in
Text(player.name)
}
.onMove(perform: move)
}
}
.navigationTitle("Game")
.navigationBarTitleDisplayMode(.inline)
}
}
func move(from source: IndexSet, to destination: Int) {
game.players.move(fromOffsets: source, toOffset: destination)
}
}
这里的问题是,您移动的不是普通数组的元素,而是移动的是关系数组属性。
所以,据我了解,基本上发生的情况是,当您执行移动并更改数组时,这会触发 SwiftUI 更新视图,这意味着它将访问
players
的 game
属性。
我在日志中看不到任何痕迹,因此
game
将简单地返回它所拥有的数组以及最初排序的数组。
如果你想这样做并保留这个新订单,你必须有一些属性来保存玩家订单并将其保留在
onMove
中,这当然会变得更加复杂,因为你有多对多的关系。
要向此答案添加一些代码:) 这是一个示例,说明如何使
onMove
以简单的方式工作,但当然这不会持续存在。我仍然认为它有价值,因为它表明 onMove
有效,但不仅仅是当您直接在关系属性上使用它时。
struct GameView: View {
var game: Game
@State var players: [Player]
init(game: Game) {
self.game = game
self.players = game.players
}
var body: some View {
NavigationStack {
Form {
Section("Spieler") {
ForEach(players) { player in
Text(player.name)
}
.onMove(perform: move)
}
}
.navigationTitle("Game")
.navigationBarTitleDisplayMode(.inline)
}
}
func move(from source: IndexSet, to destination: Int) {
players.move(fromOffsets: source, toOffset: destination)
}
}