Наблюдение за изменениями в наборе результатов Realm - PullRequest
0 голосов
/ 08 ноября 2018

Я работаю над приложением для iOS, которое использует базу данных Realm. В моем AppDelegate я определяю набор результатов Realm следующим образом:

var results: Results<RealmWidget>!
var notificationToken: NotificationToken? = nil

do {
    let realm = try Realm()
    if results == nil {
        results = realm.objects(RealmWidget.self)
    }
} catch {
    print(error.localizedDescription)
}

Я наблюдаю этот набор результатов для таких изменений:

if notificationToken == nil {
    notificationToken = results.observe { (changes: RealmCollectionChange) in
        switch changes {
        case .update(_, _, let insertions, _):
            if insertions.count > 0 {
                // show badge on tab bar
                // play sound to get the user's attention
            }
        default:
            break
        }
    }
}

Каждый раз, когда новый объект RealmWidget вставляется в базу данных (что происходит в результате получения данных с сервера), я хочу показать значок на UITabBar в моем пользовательском интерфейсе. Этот код работает правильно.

В другой части моего приложения у меня есть контроллер представления с UITableView, который используется для отображения всех объектов RealmWidget (отсортированных по отметке времени). Внутри этого контроллера представления у меня также есть набор результатов, который я наблюдаю за изменениями, чтобы я знал, когда нужно перезагрузить просмотр таблицы. Этот код выглядит так:

var results: Results<RealmWidget>!
var notificationToken: NotificationToken? = nil

class MyViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

  override func viewDidLoad() {
      super.viewDidLoad()

      results = RealmHelper.getRealmWidgets() // helper method that  queries Realm for all of the Widget objects and sorts them by timestamp
      notificationToken = results.observe { [weak self] (changes: RealmCollectionChange) in
          DispatchQueue.main.async {
              self!.tableView.reloadData()
          }
      }
  }
}

Этот код также, казалось, работал правильно, пока я не добавил код для воспроизведения звука в блок наблюдения в моем AppDelegate. Затем я понял, что каждый раз, когда я удаляю строку из UITableView в этом контроллере представления, я также слышал воспроизведение звука. Это было неожиданно, потому что я должен был только добавить значок в UITabBar и воспроизводить звук, когда есть вставка, а не удаление.

Я добавил отладочный код в блок наблюдения, который определен в моем AppDelegate, поэтому он выглядит следующим образом:

if notificationToken == nil {
    notificationToken = results.observe { (changes: RealmCollectionChange) in
        switch changes {
        case .update(_, let deletions, let insertions, let modifications):
            print("widget deletion count: \(deletions.count)")
            print("widget insertion count: \(insertions.count)")
            print("widget modification count: \(modifications.count)")
            if insertions.count > 0 {
                // show badge on tab bar
                // play sound to get the user's attention
            }
        default:
            break
        }
    }
}

Когда я запускаю приложение, переключаюсь на контроллер представления с табличным представлением, а затем удаляю одну из строк (что приводит к удалению соответствующего объекта RealmWidget из базы данных), я вижу следующий вывод, напечатанный в отладке консоль:

widget deletion count: 2
widget insertion count: 1
widget modification count: 0

Несколько вещей по этому поводу мне неясны:

  • почему счетчик удалений 2, когда я удалил только один объект RealmWidget?
  • почему счетчик вставок 1, когда я не добавил / не вставил объекты RealmWidget?

Если кто-нибудь сможет объяснить, что здесь происходит, я, безусловно, буду благодарен за помощь!

- РЕДАКТИРОВАТЬ -

Я добавил тот же отладочный код в свой блок наблюдения, который определен внутри контроллера представления, и заметил еще кое-что странное. Когда возникает эта «проблема», я вижу этот вывод в консоли отладки:

widget deletion count (AppDelegate): 2
widget insertion count (AppDelegate): 1
widget modification count (AppDelegate): 0

widget deletion count (View controller): 1
widget insertion count (View controller): 0
widget modification count (View controller): 0

Таким образом, блок наблюдения в моем контроллере вида показывает 1 удаление, а блок наблюдения в моем AppDelegate показывает 2 удаления и 1 вставку! Как ни странно, это не происходит в 100% случаев. Если мой UITableView показывает 10 RealmWidget объектов, и я удаляю их по одному, примерно в 75% случаев, я вижу вышеприведенный вывод в консоли. Но в остальные 25% случаев результат - именно то, что я ожидал увидеть:

widget deletion count (AppDelegate): 1
widget insertion count (AppDelegate): 0
widget modification count (AppDelegate): 0

widget deletion count (View controller): 1
widget insertion count (View controller): 0
widget modification count (View controller): 0

1 удаление в обоих блоках наблюдения. Я сейчас еще больше сбит с толку, чем раньше! ; -)

- РЕДАКТИРОВАТЬ № 2 -

Похоже, что это связано с тем, что Results<RealmWidget> в моем AppDelegate и Results<RealmWidget> в моем контроллере представления не упорядочивают результаты запроса одинаково.

В моем AppDelegate, results - несортированная коллекция всех RealmWidget объектов в Царстве. Но в моем контроллере представления вспомогательный метод, который я использую для определения results, представляет собой отсортированную коллекцию всех RealmWidgets объектов в области.

1 Ответ

0 голосов
/ 07 мая 2019

Я отправил этот вопрос в Realm через GitHub и получил следующий ответ:

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

В настоящее время мы сообщаем об объекте в конце перемещения к месту удаленный объект, так как этот объект также удаляется, а затем вставляется в новое местоположение.

https://github.com/realm/realm-cocoa/issues/6130

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...