I'm currently programming my first SwiftData app.
I created two models:
Player.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
}
}
Game.swift:
@Model
final class Game {
@Relationship var players: [Player]
init(players: [Player] = []) {
self.players = players
}
}
If I display the players of a game using the players variable, the order is always the same but I don't know why and what the sort descriptor is. If want to use .move to rearrange the order, but it doesn't work. The Player instantly jumps back. If I use .append(), the Player always appends at the same position, depending on which I use. For example, if I add Player(games: [], name: "Frank", id: UUID())
, it always appends at second position, while Player(games: [], name: "Sean", id: UUID())
always appends on fourth position.
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)
}
}
The problem here is that you are not moving the elements of an ordinary array but an array property that is an relationship.
So basically what happens, as I understand it, is that when you perform the move and change the array this triggers SwiftUI to update the view which means it will access the
players
property ofgame
.I can't see any trace of this in the logs so the
game
will simply return the array it has and as it was sorted originally.If you want to do it this way and persist this new order you must have some property that holds a players order and persist it in
onMove
, this of course gets extra complicated since you have a many to many relationship.To add some code to this answer :) here is an example on how you can make
onMove
work in a simple maner but of course this isn't persisted. I still think it has a value since it shows thatonMove
works but not just when you use it directly on a relationship property.