我有一个名为CardDetails的模型
public class CardDetails: Object {
@objc public dynamic var id : Int = 0
@objc public dynamic var number : String?
@objc public dynamic var name : String?
@objc public dynamic var status : String?
override public static func primaryKey() -> String? {
return "id"
}
override public static func indexedProperties() -> [String] {
return ["status"]
}
}
当我们从API
获取数据时,该对象被写在后台线程上let realm = try Realm()
try realm.write {
for card in cardsList {
realm.add(card,update: true)
}
}
我在ViewController中使用了NotificationToken,如下所示
var cardResults: Results<CardDetails>!
override func viewDidLoad() {
super.viewDidLoad()
cardResults = realm.objects(CardDetails.self).filter("status = %@", "ACTIVE")
tokenCards = cardResults.observe { [weak self] (changes: RealmCollectionChange) in
switch(changes) {
case .initial, .update:
self?.setUpCardUI()
case .error(let error):
// An error occurred while opening the Realm file on the background worker thread
fatalError("\(error)")
}
}
}
问题是我在每次调用卡取出端点时都会调用setUpCardUI,虽然数据没有改变(只有一个活动卡!)。这导致意外的UI行为。
答案 0 :(得分:0)
您是否已尝试将更新设置为false并在写入完成后更新UI。
let realm = try Realm()
try realm.write {
for card in cardsList {
realm.add(card,update: false)
}
//Perhaps try updating the UI when it finished writing to realm
}
答案 1 :(得分:0)
发生了什么事
1)我获取领域数据中的现有数据并进行显示。
2)从服务器加载新数据。
3)带有SAME数据,但领域仍会在其通知中发送修改更改。
因此,当数据从服务器返回并触发通知块时,tableView会跳起来。
存在以下领域问题:https://github.com/realm/realm-java/issues/5451,https://github.com/realm/realm-core/issues/2787,https://github.com/realm/realm-cocoa/issues/3489
答案 2 :(得分:0)
无论数据是否更改,Realm始终会在更新对象时发送修改更改,这真是令人不快,但这并不意味着我们无法解决问题,甚至无法实现一些不错的改进。
我们希望手动插入,删除或重新加载单元格,而不是在观察到更改时重新加载整个表视图。我编写了一个扩展程序以在表视图上执行此操作。
import UIKit
// RealmDiff is just a lightweight struct to make passing the changes around cleaner
// public struct RealmDiff {
// let deletions: [Int]
// let insertions: [Int]
// let modifications: [Int]
//}
extension UITableView {
func reload(section: Int = 0, with diff: RealmDiff?, update: ((UITableViewCell, IndexPath) -> Void)? = nil) {
guard let diff = diff else {
reloadData()
return
}
beginUpdates()
insertRows(at: diff.insertions.map({ IndexPath(row: $0, section: section) }), with: .automatic)
deleteRows(at: diff.deletions.map({ IndexPath(row: $0, section: section) }), with: .automatic)
guard update != nil else {
reloadRows(at: diff.modifications.map({ IndexPath(row: $0, section: section) }), with: .fade)
endUpdates()
return
}
endUpdates()
let indexPaths = diff.modifications
.map ({ IndexPath(row: $0, section: 0) })
.filter { indexPathsForVisibleRows?.contains($0) ?? false }
indexPaths.forEach {
if let cell = cellForRow(at: $0) {
update?(cell, $0)
}
}
}
}
默认情况下,这仍将交换所有单元格,这可能仍会导致表格视图根据布局的实现而跳转。但是我们也可以传递一个闭包来手动更改单元格上的数据。这是使用中的扩展程序的示例:
tableView.reload(with: diff) { [weak self] cell, indexPath in
if let cell = cell as? MyCellClass {
MyCellClass.configure(cell: cell, with: myDataSourceDataArray[indexPath.row], delegate: self)
}
}
这样,您使用的是同一单元,不需要重新加载。我发现这种方法非常有效,并且非常可重用。