ayelvs
ayelvs

Reputation: 601

How can I reorder the data in my list SwiftData?

I understand that we can sort and order directly in @Query, however I'm trying to implement a feature to allow user to manually sort using List (in edit mode)

@Query(sort: \FavouriteCommunity.order) private var favouriteCommunities: [FavouriteCommunity]

List {
    Section("Top communities") {
        // Some other views
    }
    Section("Favorites") {
        ForEach(favouriteCommunities) { item in
            NavigationLink(value: item) {
                FavouriteCommunityCellView(item: item)
            }
        }
        .onMove { from, to in
            favouriteCommunities.move(fromOffsets: from, toOffset: to)
        }
    }
}

I get an error: Cannot use mutating member on immutable value: 'favouriteCommunities' is a get-only property

I can actually edit the item in FavouriteCommunityCellView(item: item) when I use @Bindable so I'm aware editing is possible on the object level. It seems that query is unable to be mutated, so curious if anyone have any suggestion on how to create a re-order feature on top of SwiftData. Thanks!

Upvotes: 1

Views: 2132

Answers (1)

Brian Trzupek
Brian Trzupek

Reputation: 5390

I had a similar problem. Here is my solution applied to your specific example. I hope this helps.

.onMove(perform: { indices, newOffset in
        var s = favouriteCommunities.sorted(by: { $0.order < $1.order })
        s.move(fromOffsets: indices, toOffset: newOffset)
        for (index, item) in s.enumerated() {
                item.order = index
        }
        try? self.modelContext.save()
 })

Essentially you do the following:

  1. create a mutable local variable 's' sorted the same as your SwiftData Query.
  2. Utilize the swift move(...) function on that array, 's'
  3. Then use the enumerated() function on 's', in a for loop with an index and item to set all the indices on the data from your query.
  4. Save your objects.

Upvotes: 11

Related Questions