ios - Realm 中有没有办法为嵌套对象实现 order_by

标签 ios swift realm sql-order-by

当我使用 realm.objects() 检索父对象时,我试图检索按特定顺序排序的嵌套对象。同样重要的是,如果任何嵌套对象被修改,则保持排序顺序。

我搜索了相关问题,但它们要么已过时,要么与我描述的问题不完全相同

这是一个例子:我在 Realm 中有“用户”,每个用户都有“任务”(为清楚起见省略了无关的字段)

class task: Object {
    @objc dynamic var priority = 10
}

class user: Object {
    @objc dynamic var name = ""
    let tasks = List<task>()
}

我创建了几个用户,然后为任何给定用户附加任务(我的 UI 中的一个表,其中包含每个用户的部分和该用户的任务作为该用户部分中的行,按优先级排序)。

默认优先级从 10 开始,可以随时在 1-10 的范围内更改。

当我检索用户时:

// (1)
users = realm.objects(user.self).sorted(byKeyPath: "name")

我想检索他们按优先级排序的任务。

请注意,在初始检索用户后修改了优先级(这意味着结果的任务对象的优先级在 realm.write() 下发生了变化)。为了澄清,在我的代码中的某处,对于给定用户的任务,我执行以下操作:

realm.write() {
    task1.priority = newPriority
?

这意味着用户的任务列表应该始终按优先级排序,而不需要重复上面的 (1)。我无法对 user.tasks 属性进行排序,因为它是一个“let”变量。

请注意,用户和任务对象都有排序顺序。

我可以在更新上面的“优先级”后对任务进行索引(删除/添加),但还没有尝试过。然而,与其手动执行此操作(并假设它有效,并假设在重新排序的同时没有删除/添加“任务”,...),这不是 ORM 背后的整个想法,使这样事情简单明了?

无论如何都要这样做?在 Realm 上有扩展吗? ???对替代方法与嵌套对象的建议持开放态度。

最佳答案

很好的问题和真正展示 Realms 实时更新能力的答案。

重述问题

A user has tasks and we want to work with those tasks as an ordered list, and if there's a change to the order, keep them ordered by the new order

使用问题中提供的两个类,我们有一个按钮调用一个函数来查询用户的 Realm 并将该用户存储在类 var 中

var myUser: UserClass!

func loadUser() {
    if let realm = gGetRealm() { //my code to connect to Realm
        let userResults = realm.objects(UserClass.self)
        if userResults.count > 0 {
            let user = userResults[0]
            self.myUser = user
        }
    }
}

然后一个按钮调用一个函数来简单地打印出用户任务,按优先级排序

func printOrderedTasks() {
    let sortedTasks = self.myUser.tasks.sorted(byKeyPath: "priority")
    for task in sortedTasks {
        print(task)
    }
}

所以对于这个例子,我创建了 4 个任务,并将它们添加到用户任务列表并将用户写入 Realm ,优先级初始顺序是:10、0、1、4

然后 loadUser 加载并存储第一个可用的用户,并将其分配给类 var。

printOrderedTasks 按升序输出任务。所以加载用户后,点击 printOrderedTasks 输出是

0
1
4
10

然后,使用 Realm Studio,将 1 更改为 6 并再次单击 printOrderedTasks,输出为

0
4
6
10

无需重新加载任何东西。

只要您在代码中引用了 Realm 对象,Realm 对象就会实时更新,任何更改都会实时反射(reflect)出来。

您可以通过向该对象添加一个观察者来对此进行扩展,Realm 将通知该事件的应用程序,您可以向该事件重新加载 tableView 或让用户知道更改。

编辑:

更进一步,用户任务也是实时更新对象,如果您对它们设置排序,这些结果将保持它们的排序。

例如,让我们重写上面的代码来跟踪维护实时排序的用户任务。我重写了上面的代码并删除了用户类 var 并添加了一个任务类 var。请注意,我们永远不需要对任务重新排序,排序顺序是初始设置的,从那时起它们将保持排序。

var myUserTasks: Results<TaskClass>!

func loadUserAndGetTasks() {
    if let realm = gGetRealm() {
        let userResults = realm.objects(UserClass.self)
        if userResults.count > 0 {
            let user = userResults[0]
            self.myUserTasks = user.tasks.sorted(byKeyPath: "priority")
        }
    }
}

func printTasks() {
    for t in self.myUserTasks {
        print(t)
    }
}

初始顺序为 10、0、1、4,如上。如果我们随后使用 Realm Studio 将 1 更改为 6,然后运行 ​​printTasks 函数,您将看到排序已自动完成,因为结果是实时更新的。

0
4
6
10

这里很酷的一点是您不需要继续执行任务 - 它们会保持排序顺序。

关于ios - Realm 中有没有办法为嵌套对象实现 order_by,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56152818/

相关文章:

android - RecyclerView 使用基于 Realm 的 Adapter 进行拖放

ios - 如何拦截来自共享扩展的远程通知?

iOS 播放视频的速度超过 2 倍?

ios - 如何创建三态开关按钮?

Swift - boolean 与 boolean

ios - 选择 TableView 中的每个单元格时呈现不同的 View

ios - Realm swift "Object has been deleted or invalidated"

ios - Realm swift : instance member cannot be used on type

ios - DrawView保存组合图(相乘)

ios - 在另一个 View 中从列表中选择项目