我在用
Realm
作为一个缓存层,每当数据呈现给用户时,它都会首先从数据库中取出并显示给用户。随后,将发送一个服务器请求,以获取最新版本的数据,并将其与
领域
数据库,并在
UICollectionView
.
问题是,当缓存的数据从
领域
数据库和
UICollectionView
如果正在更新,则服务器的更新请求可能在
UICollectionView
加载了所有的单元格,从
Results
列表是一个实时的数据集合,可以修改。例如,如果在服务器端删除了一个项目,那么live collection将少保存一个项目,因此会导致越界异常。
尽管如此,即使是官方提供的代码
领域
考虑到
results
可以在
UITableView
一行一行地问:
class ViewController: UITableViewController {
var notificationToken: NotificationToken? = nil
override func viewDidLoad() {
super.viewDidLoad()
let realm = try! Realm()
let results = realm.objects(Person.self).filter("age > 5")
// Observe Results Notifications
notificationToken = results.observe { [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()
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()
case .error(let error):
// An error occurred while opening the Realm file on the background worker thread
fatalError("\(error)")
}
}
}
deinit {
notificationToken?.invalidate()
}
}
我唯一能想到的解决方法是创建一个结果的深层副本,以及使用信号量或类似物来同步观察函数的主体,以确保数据不会进入不一致的状态,这是我认为非常低效的状态。(注意
tableView.endUpdates()
这并不意味着
UtableView
已重新加载所有数据,但它只是被分派到队列中,并准备以异步方式进行处理。)
我想听听关于如何以有效的方式实施这一点的任何建议,以消除提到的种族条件。