EN VI

SwiftData Query sort of a property array of items by date?

2024-03-16 04:00:08
How to SwiftData Query sort of a property array of items by date

I am learning SwiftData and would like to use it to convert my current app to use SwiftData. I am trying to construct a SwiftDate Query to sort an array of Items by date. The Items array is a property within the main model. All examples I have seen have a Query that uses the first level attribute to sort on (@Query(sort: \TaskItem.name) var tasks: [TaskItem]) but I am looking at a Query to sort on the second level (TaskItems.items.date). I am looking for help/direction. See my models below

@Model
final class TaskItems {
    @Attribute(.unique) var name: String
    @Relationship(deleteRule: .cascade)
    var items: [Item]?
    
    init(name: String, items: [Item]? = nil) {
        self.name = name
        self.items = items
    }
}

@Model
final class Item {
    @Attribute(.unique) let id = UUID().uuidString
    var tag: String
    var date: Date
    
    init(tag: String, date: Date) {
        self.tag = tag
        self.date = date
    }
}

In my View, I have the main Query as

@Query var taskItems: [TaskItems]

and I am trying to display the Items which is a property of TaskItems sorted by the date.

Here is what I tried which I know is not right and does not compile.

@Query(FetchDescriptor<Item>(sortBy: [SortDescriptor(\TaskItems.items.date, order: .forward)])) var items: [Item]

Appreciate any direction/help

Solution:

To solve this with a @Query you first need to update your models by fully defining the relationship between them.

  • Add a reference to TaskItems in Item, the property needs to be optional since the other end is optional for the predicate to work
var task: TaskItems?
  • Update the Relationship in TaskItems by defining what the inverse property is
@Relationship(deleteRule: .cascade, inverse: \Item.task) 
var items: [Item]?
  • Add the query to the sub-view
@Query(filter: Predicate<Item>.false) private var items: [Item]

init(task: TaskItems) {
    let id = task.persistentModelID
    let fetchDescriptor = FetchDescriptor<Item>(predicate: #Predicate { $0.task?.persistentModelID == id},
                                                sortBy: [SortDescriptor(\.date, order: .forward)])
    _items = Query(fetchDescriptor)
 }
Answer

Login


Forgot Your Password?

Create Account


Lost your password? Please enter your email address. You will receive a link to create a new password.

Reset Password

Back to login