Reputation: 1773
I am using RealmSwift. Data is a one-to-many relationship.
I'm having trouble because I don't know how to sort the list in RealmSwift.
I want to sort the tasks linked to the TaskList.
Thank you.
class TaskList: Object, Identifiable {
@objc dynamic var id = NSUUID().uuidString
@objc dynamic var title = ""
@objc dynamic var createdAt = NSDate()
var tasks: List<Task> = List<Task>()
override static func primaryKey() -> String? {
return "id"
} }
class Task: Object, Identifiable {
@objc dynamic var id = NSUUID().uuidString
@objc dynamic var title = ""
@objc dynamic var createdAt = NSDate()
private let lists = LinkingObjects(fromType: TaskList.self, property: "tasks")
var list: TaskList { return list.first! }
override static func primaryKey() -> String? {
return "id"
} }
Upvotes: 0
Views: 96
Reputation: 35657
I think this is a one line answer. If you know which TaskList object you want to get the tasks for, and you want them ordered by say, creation date. This will do it
let taskResults = realm.objects(Task.self)
.filter("ANY lists == %@", taskList)
.sorted(byKeyPath: "createdAt")
Upvotes: 0
Reputation: 5073
If you want your tasks stored in an ordered fashion you'll have to manually do an ordered insert.
extension List {
func insert<V: Comparable>(_ object: Element, orderedBy keyPath: KeyPath<Element, V>) {
var index = 0
for i in 0..<count {
if self[i][keyPath: keyPath] >= object[keyPath: keyPath] {
break
}
index = i + 1
}
insert(object, at: index)
}
}
let list = TaskList()
let tasks = [
Task(title: "J"),
Task(title: "Z"),
Task(title: "T"),
Task(title: "J"),
Task(title: "Z"),
]
tasks.forEach {
list.tasks.insert($0, orderedBy: \.title)
}
However, I find it much easier to keep Lists
unsorted and retrieve sorted Results
whenever I need to display the data. To sort by a single property just call sorted(byKeyPath:)
:
let sortedTasks = taskList.tasks.sorted(byKeyPath: "title")
To sort by multiple fields call sorted(by:)
:
let sortedTasks = taskList.tasks.sorted(by: [
SortDescriptor(keyPath: "title"),
SortDescriptor(keyPath: "createdAt")
])
Alternatively, you can add a sorted property to your Model:
class TaskList: Object, Identifiable {
@objc dynamic var id = UUID().uuidString
@objc dynamic var title = ""
@objc dynamic var createdAt = Date()
var tasks = List<Task>()
lazy var sortedTasks: Results<Task> = tasks.sorted(byKeyPath: "title")
override class func ignoredProperties() -> [String] {
return ["sortedTasks"]
}
override static func primaryKey() -> String? {
return "id"
}
}
Upvotes: 1
Reputation: 54716
You cannot get a LinkingObjects
itself to be sorted, but you can call LinkingObjects.sorted(byKeyPath:)
, which returns a Results
instance containing all elements of the LinkingObjects
, just sorted.
class Task: Object, Identifiable {
@objc dynamic var id = NSUUID().uuidString
@objc dynamic var title = ""
@objc dynamic var createdAt = NSDate()
private let lists = LinkingObjects(fromType: TaskList.self, property: "tasks")
lazy var sortedLists = lists.sorted(byKeyPath: "createdAt")
var list: TaskList { return list.first! }
override static func primaryKey() -> String? {
return "id"
}
}
Upvotes: 0