我很难找到 NSDiffableDataSourceSnapshot 的用途reloadItems(_:)
:
如果我要求重新加载的项目与数据源中已经存在的项目不相等,我会崩溃:
由于未捕获的异常“NSInternalInconsistencyException”而终止应用程序,原因:“尝试重新加载快照中不存在的项目标识符:ProjectName.ClassName
但是,如果该项目等同于数据源中已经存在的项目,那么“重新加载”它的意义何在?
您可能会认为第二点的答案是:嗯,项目标识符对象的某些其他方面可能不是其等价性的一部分,但确实反映到单元格界面中。但我发现那不是真的。调用后reloadItems
,表视图不反映更改。
因此,当我想更改一个项目时,我最终对快照所做的是insert
要替换的项目之后,然后是delete
原始项目的 a。没有快照replace
方法,这正是我希望reloadItems
的结果。
reloadItems
(我对这些术语进行了Stack Overflow 搜索,但发现的很少——主要是几个对. ,有人发现这种方法有什么实际用途?)
好吧,没有什么比拥有一个可重复的最小示例更可取的了,所以这里有一个。
使用模板 ViewController 制作一个普通的 iOS 项目,并将此代码添加到 ViewController。
我一块一块来。首先,我们有一个结构将用作我们的项目标识符。UUID 是唯一的部分,因此等价性和哈希性仅取决于它:
struct UniBool : Hashable {
let uuid : UUID
var bool : Bool
// equatability and hashability agree, only the UUID matters
func hash(into hasher: inout Hasher) {
hasher.combine(uuid)
}
static func ==(lhs:Self, rhs:Self) -> Bool {
lhs.uuid == rhs.uuid
}
}
接下来,(假)表视图和可区分的数据源:
let tableView = UITableView(frame: .zero, style: .plain)
var datasource : UITableViewDiffableDataSource<String,UniBool>!
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
self.datasource = UITableViewDiffableDataSource<String,UniBool>(tableView: self.tableView) { tv, ip, isOn in
let cell = tv.dequeueReusableCell(withIdentifier: "cell", for: ip)
return cell
}
var snap = NSDiffableDataSourceSnapshot<String,UniBool>()
snap.appendSections(["Dummy"])
snap.appendItems([UniBool(uuid: UUID(), bool: true)])
self.datasource.apply(snap, animatingDifferences: false)
}
所以在我们的 diffable 数据源中只有一个 UniBool 并且它bool
是true
. 所以现在设置一个按钮来调用这个操作方法,它试图bool
通过使用来切换值reloadItems
:
@IBAction func testReload() {
if let unibool = self.datasource.itemIdentifier(for: IndexPath(row: 0, section: 0)) {
var snap = self.datasource.snapshot()
var unibool = unibool
unibool.bool = !unibool.bool
snap.reloadItems([unibool]) // this is the key line I'm trying to test!
print("this object's isOn is", unibool.bool)
print("but looking right at the snapshot, isOn is", snap.itemIdentifiers[0].bool)
delay(0.3) {
self.datasource.apply(snap, animatingDifferences: false)
}
}
}
事情就是这样。我对reloadItems
一个 UUID 匹配但bool
被切换的项目说:“这个对象的 isON 是假的”。但是当我问快照时,好吧,你有什么?它告诉我它唯一的项目标识符bool
仍然是 true。
这就是我要问的。如果快照不会获取 的新值bool
,那么首先是reloadItems
为了什么?
显然,我可以只替换一个不同的UniBool,即一个具有不同 UUID 的 UniBool。但是我不能打电话reloadItems
;我们崩溃是因为 UniBool 还没有在数据中。我可以通过调用来解决这个问题insert
,remove
这正是我解决它的方法。
但我的问题是:reloadItems
如果不是为了这件事,那又是为了什么?