通过条件限制 Realm Results 中的对象,以便观察结果

Limit objects in Realm Results by condition in order to observe result

我想通过某些谓词限制领域结果中的对象,以便观察此结果并根据其更改更新我的 UI。

我见过几个解决方案争论因为领域中的对象是延迟加载的所以不需要限制查询。但是,我希望查询将结果限制在限制范围内,以便在受限制限制的对象更改时触发更改通知。

举个例子:

假设我有一个包对象:

class Package: Object {

    @objc enum State: Int {
        case scheduled
        case delivered
    }

    @objc dynamic var state = State.scheduled
    @objc dynamic var deliveryDate = Date()
}

并且我想创建所有已安排包裹的结果,并且只创建最新交付的包裹。我该怎么做呢?这甚至可以通过我可以观察变化的单个结果实现吗?

更新:

试图更清楚地了解我在寻找什么。假设我的领域中有以下软件包:

Package1
  state: delivered
  deliveryDate: March 1st

Package2
  state: delivered
  deliveryDate: March 2nd

Package3
  state: delivered
  deliveryDate: March 3rd

Package4
  state: scheduled
  deliveryDate: March 4th

Package5
  state: scheduled
  deliveryDate: March 5th

Package6
  state: scheduled
  deliveryDate: March 6th

假设这些包每天都会更改状态。所以在 3 月 3 日,数据将如上所示,但在 3 月 4 日,Package4 的状态将更改为 'delivered'。然后我想要一个结果来反映那两天的以下内容:

March 3rd:
  - Package3 (delivered)
  - Package4 (scheduled)
  - Package5 (scheduled)
  - Package6 (scheduled)

March 4th:
  - Package4 (delivered)
  - Package5 (scheduled)
  - Package6 (scheduled)

我将尝试回答,但它可能有偏差。

objective是为了有一个单一的realm结果,可以观察到变化,也知道最新的交付是什么。

这是代码

self.packageResults = realm.objects(Package.self).sorted(byKeyPath: "delivered", ascending: false)

然后观察self.packageResults.

只要有变化,observe 闭包就会触发并传递结果,降序排列,因此最新的传递将是 'at the top',即索引 0.

编辑

根据对问题的评论和更新,有人质疑此答案是否提供了解决方案。现在数据有点多,稍微修改一下就可以得到想要的结果(差不多,继续看)

self.packageResults = realm.objects(Package.self)
                           .filter("deliveryDate => 20190303")
                           .sorted(byKeyPath: "state", ascending: false)

然后将观察者添加到 self.packageResults。 (请注意,我使用 Int 作为时间戳以保持简单)

为了测试,我们将问题中提供的数据与我们的观察者代码一起使用。该代码打印数据的初始状态,然后打印任何删除、插入或修改后的状态。

func doObserve() {
     self.notificationToken = self.packageResults!.observe { (changes: RealmCollectionChange) in
         switch changes {
         case .initial:
             print("initial load complete")
             if let results = self.packageResults {
                 for p in results {
                     print(p.deliveryDate, p.state.rawValue)
                 }
             }
             break
         case .update(_, let deletions, let insertions, let modifications):
             if let results = self.packageResults {
                 for p in results {
                     print(p.deliveryDate, p.state.rawValue)
                 }
             }

然后我们 运行 代码并添加观察者。这是输出

initial load complete
20190303 1
20190304 0
20190305 0
20190306 0

如果我们随后将包 20190304 更改为 'delivered',我们将得到以下输出

20190303 1
20190304 1
20190305 0
20190306 0

所以我们得到了想要的结果。但是,根据问题,查询的条件会发生变化,因为下一个查询将针对 20190304 及之后的日期。

如果输出条件改变,查询条件也必须改变。在这种情况下,所需的结果是每天显示最新交付的包裹,因此需要每天更新查询以反映该日期。

作为一个可能的解决方案,更改 Package 对象以包含一个 watched 属性

class Package: Object {
    @objc enum State: Int {
        case scheduled
        case delivered
    }
    @objc dynamic var state = State.scheduled
    @objc dynamic var deliveryDate = 0
    @objc dynamic var watched = false
}

并更新查询以仅观察正在观看的包,忽略未观看的包(where watched = false)

self.packageResults = realm.objects(Package.self)
                           .filter("deliveryDate => 20190303 and watched == true")
                           .sorted(byKeyPath: "state", ascending: false)

然后,当您不再需要了解某个对象时,将它的监视 属性 设置为 false,它就不会包含在结果中。使用与上述查询相同的过程,将 20190304 更改为已交付时,我们还将 20190303 watched 属性 更改为 false,结果为

 handle item delete, insert or mod
20190304 1
20190305 0
20190306 0

这似乎回答了问题。