Я работаю над приложением для 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
объектов в области.