swiftswiftuiswiftdata

Sorting on a boolean field


I have a model that looks something like this

@Model
class TodoTask {
    var title: String
    var isDone: Bool
    var expectedOn: Date
}

I want to render a list of Tasks such that when isDone == true the item appears at the bottom of the list.

I have a Query binding similar to the one below but the boolean field errors with "No exact matches in call to initializer"

@Query(sort: [SortDescriptor(\TodoTask.expectedOn, order: .reverse), SortDescriptor(\TodoTask.isDone )]) var todoTasks: [TodoTask]

What am I doing wrong?


Solution

  • As I see it you are not doing something wrong and this should be fixed in SwiftData. A workaround for now that, unfortunately, would require a more complicated solution would be

    Remove the isDone property from the query

    @Query(sort: [SortDescriptor<TodoTask>(\.expectedOn, order: .reverse)]) var todoTasks: [TodoTask] = []
    

    Add a computed property on TodoTask that can be used for sorting, for instance

    var isDoneSort: UInt8 {
        isDone ? 1 : 0
    }
    

    and then add a new array property to sort on this and use this new array in your view instead of the query property

    var sortedTasks: [TodoTask] {
        todoTasks.sorted(using: KeyPathComparator(\TodoTask.isDoneSort))
    }