我很难找到NSDiffableDataSourceSnapshot reloadItems(_:)
的使用:
您可能会认为,第二点的答案是:好吧,项目标识符对象可能存在其他一些方面,而不是其等同性的一部分,但确实反射(reflect)到单元格接口(interface)中。但是我发现那是不对的。调用
reloadItems
后,表 View 不反射(reflect)更改。因此,当我要更改项目时,最终要对快照执行的操作是要替换的项目之后的
insert
,然后是原始项目的delete
。没有快照replace
方法,这就是我希望reloadItems
变成的方法。(我对这些术语进行了Stack Overflow搜索,却发现很少-大多数只是几个问题,这些问题使
reloadItems
的特定用途(例如How to update a table cell using diffable UITableView)感到困惑。因此,我以一种更笼统的形式问,有人发现了什么实际用途?对于这种方法?)嗯,没有什么比拥有一个可重现的最小示例更好的了,所以这里是一个。
使用其模板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
}
}
接下来,(伪)表 View 和可扩散数据源: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)
}
因此,在我们的可扩散数据源中只有一个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为false”。但是当我问快照时,好,您得到了什么?它告诉我其唯一项目标识符的bool
仍然为true。这就是我要问的问题。如果快照不准备使用
bool
的新值,那么reloadItems
首先是什么?显然,我可以用另一种UniBool代替,即用另一种UUID替代。但是后来我不能调用
reloadItems
;我们崩溃,因为该数据中还没有UniBool。我可以通过先调用insert
然后再调用remove
来解决此问题,而这正是我解决该问题的方法。但是我的问题是:那么
reloadItems
是做什么的,如果不是因为这件事呢? 最佳答案
我同意,根据您的新示例代码,它看起来像个错误。当您将reloadItems
添加到快照时,它会正确触发数据源闭包以请求更新的单元格,但是传递给闭包的IdentifierType
项是原始的,而不是reloadItems
调用提供的新值。
如果我将UniBool
结构更改为一个类,使其成为引用而不是值类型,则事情按预期进行(因为现在只有一个UniBool
实例,而不是具有相同标识符的新实例)。
目前看来,有两种可能的解决方法:
IdentifierType
使用引用而不是值类型indexPath
访问它。 我认为这些都不是理想的。
有趣的是,在将
UniBool
更改为类之后,我尝试创建一个新的UniBool
实例,该实例与现有实例具有相同的uuid
并重新加载该实例。代码崩溃,出现异常,指出为重新加载指定了无效的物品标识符;这听起来不对劲;仅hashValue
应该很重要,而不是实际的对象引用。原始对象和新对象都具有相同的hashValue
,返回的==
true
。原始答案
reloadItems
有效,但是有两个要点:snapshot
开始,并在其上调用reloadItems
。您无法创建新的快照。item
之外,您不能仅依赖传递给CellProvider
闭包的identifier
-它不表示支持模型(数组)中的最新数据。第2点表示您需要使用提供的
indexPath
或item.id
从模型中获取更新的对象。我创建了一个简单的example,它在表格行中显示当前时间;这是数据源结构:
struct RowData: Hashable {
var id: UUID = UUID()
var name: String
private let possibleColors: [UIColor] = [.yellow,.orange,.cyan]
var timeStamp = Date()
func hash(into hasher: inout Hasher) {
hasher.combine(self.id)
}
static func ==(lhs: RowData, rhs: RowData) -> Bool {
return lhs.id == rhs.id
}
}
请注意,尽管hash
函数仅使用id
属性,但也有必要重写==
,否则当您尝试重新加载该行时,将使用无效的标识符崩溃。每秒重新加载随机选择的行。当您运行代码时,您会看到时间在那些随机选择的行上进行了更新。
这是使用
reloadItems
的代码:self.timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { (timer) in
guard let datasource = self.tableview.dataSource as? UITableViewDiffableDataSource<Section,RowData> else {
return
}
var snapshot = datasource.snapshot()
var rowIdentifers = Set<RowData>()
for _ in 0...Int.random(in: 1...self.arrItems.count) {
let randomIndex = Int.random(in: 0...self.arrItems.count-1)
self.arrItems[randomIndex].timeStamp = Date()
rowIdentifers.insert(self.arrItems[randomIndex])
}
snapshot.reloadItems(Array(rowIdentifers))
datasource.apply(snapshot)
}
关于ios - NSDiffableDataSourceSnapshot `reloadItems`是干什么用的?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/64081701/