When you use @Query
to pull objects out of SwiftData, you get to specify how you want the data to be sorted – should it be alphabetically by one of the fields? Or numerically with the highest numbers first? Regardless of what you choose, it's always a good idea to choose something so your users have a predictable experience.
In this project we have various fields that might be useful for sorting purposes: the title of the book, the author, or the rating are all sensible and would be good choices, but we don't have to rely on just one – you can specify multiple, so that you might ask for highest-rated books first, then use their names for a tiebreaker.
Query sorting can be done in two ways: a simple option that allows just one sort field, and a more advanced version that allows an array of a new type called SortDescriptor
.
Using the simple version, we might ask for our books to be provided in alphabetical order based on their title:
@Query(sort: \Book.title) var books: [Book]
Or we could ask for them to be sorted by rating, highest to lowest:
@Query(sort: \Book.rating, order: .reverse) var books: [Book]
That works well when you want just one single field, but generally I'd say it's a better idea to have a backup field too – to say "sort by rating, then by title" adds an extra level of predictability to your app, which is always a good thing.
This is done using the SortDescriptor
type, which we can create them from either one or two values: the property we want to sort on, and optionally whether it should be reversed or not. For example, we can alphabetically sort on the title property like this:
@Query(sort: [SortDescriptor(\Book.title)]) var books: [Book]
Like the simpler approach to sorting, sorting results using SortDescriptor
is done in ascending order by default, meaning alphabetical order for text, but if you wanted to reverse the sort order you’d use this instead:
@Query(sort: [SortDescriptor(\Book.title, order: .reverse)]) var books: [Book]
You can specify more than one sort descriptor, and they will be applied in the order you provide them. For example, if the user added the book “Forever” by Pete Hamill, then added “Forever” by Judy Blume – an entirely different book that just happens to have the same title – then specifying a second sort field is helpful.
So, we might ask for book title to be sorted ascending first, followed by book author ascending second, like this:
@Query(sort: [
SortDescriptor(\Book.title),
SortDescriptor(\Book.author)
]) var books: [Book]
Having a second or even third sort field has little to no performance impact unless you have lots of data with similar values. With our books data, for example, almost every book will have a unique title, so having a secondary sort field is more or less irrelevant in terms of performance.
SPONSORED Ready to dive into the world of Swift? try! Swift Tokyo is the premier iOS developer conference will be happened in April 9th-11th, where you can learn from industry experts, connect with fellow developers, and explore the latest in Swift and iOS development. Don’t miss out on this opportunity to level up your skills and be part of the Swift community!
Sponsor Hacking with Swift and reach the world's largest Swift community!
Link copied to your pasteboard.