如果在初始化通知后更新结果,如何使用领域通知?

fis*_*her 1 realm uitableview ios swift

我使用带有Realm结果的UITableView作为它的数据源.结果使用领域通知进行注册,并在发生更改时更新.但是,同一个表视图有一个搜索栏,可根据用户搜索查询过滤结果.这也可以正常工作,但如果通知侦听器识别出更新,则节和行计数不匹配.这样做的正确方法是什么?是否可以更新NotificationToken?

这是初始化通知令牌的代码:

let realm = try! Realm()

results = realm.objects(Person.self).filter("active = '1'").sorted(byProperty: "name", ascending: true)

// Observe Results Notifications
notificationToken = results?.addNotificationBlock { [weak self] (changes: RealmCollectionChange) in

    guard let tableView = self?.tableView else { return }
    switch changes {
    case .initial:
        // Results are now populated and can be accessed without blocking the UI
        tableView.reloadData()
        break
    case .update(_, let deletions, let insertions, let modifications):

        // Query results have changed, so apply them to the UITableView
        tableView.beginUpdates()

        tableView.insertRows(at: insertions.map { IndexPath(row: $0, section: 0) }, with: .automatic)

        tableView.deleteRows(at: deletions.map { IndexPath(row: $0, section: 0) }, with: .automatic)
        tableView.reloadRows(at: modifications.map { IndexPath(row: $0, section: 0) }, with: .automatic)
        tableView.endUpdates()
        break
    case .error(let error):
        // An error occurred while opening the Realm file on the background worker thread
        print("Error: \(error)")
        break
    }
}
Run Code Online (Sandbox Code Playgroud)

此代码根据用户搜索输入更新结果:

func updateSearchResults(for searchController: UISearchController) {

    let searchText = searchController.searchBar.text!

    if searchText.isEmpty == false {

        results = results?.realm?.objects(Person.self).filter("active = '1'")

        results = results?.filter("name BEGINSWITH[c] %@ OR lastName CONTAINS[c] %@", searchText, searchText)

        results = results?.sorted(byProperty: "name", ascending: true)

        self.tableView.reloadData()

    }
    else {

        results = results?.realm?.objects(Person.self).filter("active = '1'").sorted(byProperty: "name", ascending: true)

        self.tableView.reloadData()
    }
}
Run Code Online (Sandbox Code Playgroud)

如果已执行搜索qwuery并且在更新领域数据库之前,则会发生NSRange异常.

kis*_*umi 7

你覆盖resultsupdateSearchResults().通知并notificationToken绑定到特定Results对象和查询.因此,如果您results通过其他查询覆盖,则应停止先前的通知,然后将通知重新添加到新results对象.

所以updateSearchResults()方法应该如下:

func updateSearchResults(for searchController: UISearchController) {
    let searchText = searchController.searchBar.text!
    if searchText.isEmpty == false {
        results = results?.realm?.objects(Person.self).filter("active = '1'")
        results = results?.filter("name BEGINSWITH[c] %@ OR lastName CONTAINS[c] %@", searchText, searchText)
        results = results?.sorted(byProperty: "name", ascending: true)
    }
    else {
        results = results?.realm?.objects(Person.self).filter("active = '1'").sorted(byProperty: "name", ascending: true)
    }

    notificationToken.stop()
    notificationToken = results?.addNotificationBlock { [weak self] (changes: RealmCollectionChange) in
        guard let tableView = self?.tableView else { return }
        switch changes {
        case .initial:
            tableView.reloadData()
            break
        case .update(_, let deletions, let insertions, let modifications):
            tableView.beginUpdates()

            tableView.insertRows(at: insertions.map { IndexPath(row: $0, section: 0) }, with: .automatic)

            tableView.deleteRows(at: deletions.map { IndexPath(row: $0, section: 0) }, with: .automatic)
            tableView.reloadRows(at: modifications.map { IndexPath(row: $0, section: 0) }, with: .automatic)
            tableView.endUpdates()
            break
        case .error(let error):
            print("Error: \(error)")
            break
        }
    }
}
Run Code Online (Sandbox Code Playgroud)