Swift 按条件限制领域结果中的对象,以便观察结果

Swift 按条件限制领域结果中的对象,以便观察结果,swift,dynamic,realm,observers,Swift,Dynamic,Realm,Observers,我想通过一些谓词来限制领域结果中的对象,以便观察这些结果并根据其更改更新我的UI 我看到一些解决方案认为,因为领域中的对象是延迟加载的,所以没有必要限制查询。但是,我希望查询按限制约束结果,以便在受限制约束的对象更改时触发更改通知 让我举个例子: 假设我有一个包对象: class Package: Object { @objc enum State: Int { case scheduled case delivered } @objc

我想通过一些谓词来限制领域结果中的对象,以便观察这些结果并根据其更改更新我的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)

我想尝试一个答案,但可能有点离谱

我们的目标是获得一个单一领域的结果,可以观察其变化,并知道最新的交付是什么

这是密码

self.packageResults = realm.objects(Package.self).sorted(byKeyPath: "delivered", ascending: false)
然后观察自我包装结果

每当发生更改时,observe闭包将启动并传递结果,按降序排序,以便最新的传递将处于“顶部”,即索引0

编辑

根据对该问题的评论和更新,有一个问题是该答案是否提供了解决方案。现在有了更多的数据,只需稍加修改即可产生所需的结果(几乎,请继续阅读)

然后将观察者添加到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及之后

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

作为一种可能的解决方案,将包对象更改为包含监视的属性

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
}
并更新查询以仅观察正在监视的包,忽略未监视的包(其中监视=false)

然后,当您不再需要了解某个对象时,将其“监视”属性设置为false,结果中将不包括该对象。使用与此查询相同的过程,当将20190304更改为已交付时,我们还将20190303 wasted属性更改为false,结果为

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

这似乎回答了问题。

嘿,杰,谢谢你抽出时间来回答。然而,它并不完全满足我的要求。我希望结果中包含所有“预定”包,而只包含最新的“已交付”包。您的解决方案将包括所有交付的包。我可能不够清楚,已经更新了我的原始帖子。@Darumar如果您只想要第一个包,请从self.packageResults获取.first元素,它将始终是最新交付的包。最新的交付将是“在顶部”,即索引0。我的问题是我观察结果以驱动对表视图的UI更改。该表视图应显示由最近交付的包和所有计划包组成的列表。如果我必须通过从结果中挑选来手动构建列表,即结果。首先,我无法利用领域更改通知中的差异。这就是为什么我希望结果反映完整的查询。事实上,我可能会得到你的建议,然后不得不编写自己的差异逻辑来驱动我的UI。如果可能的话,我更愿意利用Realm来实现这一点。@Darumar我认为这个答案可以满足您的要求。结果将包含所有计划交付的包,并包括最近交付的包-这是您在原始问题中提出的问题。您可以直接将结果用作tableView数据源,因为列出的第一项始终是最新交付的包,并且结果会实时更新,因此,如果交付了较新的包,结果将更新。也许我不清楚你在问什么?你能不能更新一下这个问题,我会尽力想出一个解决办法。谢谢你一直以来在这方面帮助我。我已经更新了我的问题,以便更好地解释我在寻找什么。在您的答案中,您按键路径“已交付”排序。我想这是你的错别字,你的意思是“交货日期”。如果这是正确的,在我看来,你的回答总是会给我按交货日期排序的包裹的完整列表。但我想要的只是处于“已交付”状态的最新包,然后是所有计划包。希望这能澄清我的问题。看起来查询的条件每天都在变化,因为所需的输出是针对未来的一天。我更新了我的答案来解决这个问题。
self.packageResults = realm.objects(Package.self)
                           .filter("deliveryDate => 20190303 and watched == true")
                           .sorted(byKeyPath: "state", ascending: false)
 handle item delete, insert or mod
20190304 1
20190305 0
20190306 0