通过条件限制“领域结果”中的对象以观察结果

时间:2019-03-07 15:03:45

标签: swift dynamic realm observers

我想通过一些谓词来限制领域结果中的对象,以便观察该结果并根据其更改来更新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会将状态更改为“已交付”。然后,我希望得到能在这两天反映以下内容的结果:

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

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

1 个答案:

答案 0 :(得分:1)

我要尝试答案,但是可能不正确。

目标是拥有一个单一的领域结果,可以观察到变化并知道最新的交付结果。

这是代码

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

然后观察self.packageResults。

只要有更改,observation闭包就会触发并传递结果,并以降序排列,因此最新传递将位于“顶部”,即索引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更改为“已交付”,则会得到以下输出

20190303 1
20190304 1
20190305 0
20190306 0

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

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

作为一种可能的解决方案,更改Package对象以包括受监视的属性

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
}

并更新查询以仅观察正在监视的软件包,忽略不监视的软件包(其中watched = false)

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

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

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

似乎可以回答问题。