Ограничить объекты в результатах области по условию, чтобы наблюдать результат - PullRequest
0 голосов
/ 07 марта 2019

Я хочу ограничить объекты в результатах области некоторым предикатом, чтобы наблюдать за этими результатами и обновлять мой пользовательский интерфейс на основе его изменений.

Я видел несколько решений, утверждающих, что, поскольку объекты в области загружаются лениво, нет необходимости ограничивать запрос. Однако я бы хотел, чтобы запрос ограничивал результаты лимитом, чтобы уведомления об изменениях срабатывали при изменении объектов, ограниченных лимитом.

Позвольте привести пример:

Предположим, у меня есть объект пакета:

class Package: Object {

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

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

и я хочу создать результаты для всех запланированных пакетов И ТОЛЬКО для самого нового доставленного пакета. Как бы я поступил так? Возможно ли это даже с одним Результатом, который я мог бы наблюдать за изменениями?

UPDATE:

Пытаясь быть более ясным в отношении того, что я ищу. Допустим, у меня есть следующие пакеты в моей сфере:

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 марта данные будут выглядеть так, как указано выше, но 4 марта Package4 изменил бы состояние на «доставлено». Затем я хочу получить результаты, которые будут отражать следующее в эти два дня:

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

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

1 Ответ

1 голос
/ 08 марта 2019

Я собираюсь попытаться ответить, но он может быть неосновным.

Цель состоит в том, чтобы получить единый результат из области, который можно наблюдать за изменениями, а также узнать, что является новейшей доставкой.

Вот код

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

Затем наблюдайте self.packageResults.

Каждый раз, когда есть изменение, закрытие наблюдения срабатывает и доставляет результаты, отсортированные по убыванию, поэтому самая последняя доставка будет 'вверху ', то есть индекс 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, чтобы включить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
}

и обновлять запрос, чтобы наблюдать только пакеты, которые просматриваются, игнорировать те, которые не просматриваются (где наблюдалось = ложь)

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

Затем, когда вам больше не нужнознать об объекте, установить для свойства watched значение false, и оно не будет включено в результаты.Используя тот же процесс, что и выше с этим запросом, при изменении 20190304 на поставленный, мы также меняем наблюдаемое свойство 20190303 на false, и в результате получаем

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

, что, по-видимому, отвечает на вопрос.

...