我想对 RealmSwift 列表进行排序

I want to sort the List of RealmSwift

我正在使用 RealmSwift。 数据是一对多的关系。

我遇到了麻烦,因为我不知道如何在 RealmSwift 中对列表进行排序。

我想对链接到任务列表的任务进行排序。

谢谢。

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"
    } }

您无法对 LinkingObjects 本身进行排序,但您可以调用 LinkingObjects.sorted(byKeyPath:),其中 returns 是包含 [=11] 所有元素的 Results 实例=], 刚刚排序。

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"
    }
}

如果您希望以有序的方式存储您的任务,则必须手动进行有序插入。

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([=10=], orderedBy: \.title)
}

但是,我发现在需要显示数据时保持 Lists 未排序并检索已排序 Results 更容易。要按单个 属性 排序,只需调用 sorted(byKeyPath:):

let sortedTasks = taskList.tasks.sorted(byKeyPath: "title")

要按多个字段排序调用 sorted(by:):

let sortedTasks = taskList.tasks.sorted(by: [
    SortDescriptor(keyPath: "title"),
    SortDescriptor(keyPath: "createdAt")
])

或者,您可以将排序的 属性 添加到您的模型中:

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"
    }
}

我认为这是一个单行答案。如果您知道要为哪个 TaskList 对象获取任务,并且希望它们按创建日期排序。这样就可以了

let taskResults = realm.objects(Task.self)
                       .filter("ANY lists == %@", taskList)
                       .sorted(byKeyPath: "createdAt")