Ios 如何在使用UITableViewDiffableDataSource时移动UITableView单元格?
我试图使我的Ios 如何在使用UITableViewDiffableDataSource时移动UITableView单元格?,ios,swift,uitableview,uikit,Ios,Swift,Uitableview,Uikit,我试图使我的tableView单元格可移动,但它需要来自uitableview数据源协议的2或3个函数,如果我试图在我的viewController中实现委托,它将要求numberOfRowsInSection和cellforrowatinexpath函数,这些函数已经包含在新的UITableViewDiffableDataSource中 如何在使用新的UITableViewDiffableDataSource时实现此行为?我可以通过如下子类化UITableViewDiffableDataSou
tableView单元格
可移动,但它需要来自uitableview数据源
协议的2或3个函数,如果我试图在我的viewController
中实现委托,它将要求numberOfRowsInSection
和cellforrowatinexpath
函数,这些函数已经包含在新的UITableViewDiffableDataSource
中
如何在使用新的
UITableViewDiffableDataSource
时实现此行为?我可以通过如下子类化UITableViewDiffableDataSource
类来实现这一点:
类MyDataSource:UITableViewDiffableDataSource{
重写func tableView(tableView:UITableView,moveRowAt sourceIndexPath:IndexPath,to destinationIndexPath:IndexPath){
//更新真相来源的代码
//从你的真相来源拍一张新的快照
//应用(快照、动画差异:false)
}
}
然后,您可以覆盖实现所需的任何数据源方法。为了充实您的答案,下面是一个完整的实现:
class MovableTableViewDataSource: UITableViewDiffableDataSource<Int, Int> {
override func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
super.tableView(tableView, moveRowAt: sourceIndexPath, to: destinationIndexPath)
var snapshot = self.snapshot()
if let sourceId = itemIdentifier(for: sourceIndexPath) {
if let destinationId = itemIdentifier(for: destinationIndexPath) {
guard sourceId != destinationId else {
return // destination is same as source, no move.
}
// valid source and destination
if sourceIndexPath.row > destinationIndexPath.row {
snapshot.moveItem(sourceId, beforeItem: destinationId)
} else {
snapshot.moveItem(sourceId, afterItem: destinationId)
}
} else {
// no valid destination, eg. moving to the last row of a section
snapshot.deleteItems([sourceId])
snapshot.appendItems([sourceId], toSection: snapshot.sectionIdentifiers[destinationIndexPath.section])
}
}
apply(snapshot, animatingDifferences: false, completion: nil)
}
}
类MovableTableViewDataSource:UITableViewDiffableDataSource{
重写func tableView(tableView:UITableView,moveRowAt sourceIndexPath:IndexPath,to destinationIndexPath:IndexPath){
tableView(tableView,moveRowAt:sourceindepath,to:destinationindepath)
var snapshot=self.snapshot()
如果让sourceId=itemIdentifier(for:sourceIndexPath){
如果让destinationId=itemIdentifier(for:destinationIndexPath){
guard sourceId!=destinationId else{
return//目标与源相同,不移动。
}
//有效的源和目标
如果sourceIndexPath.row>destinationIndexPath.row{
snapshot.moveItem(sourceId,beforeItem:destinationId)
}否则{
snapshot.moveItem(sourceId,afterItem:destinationId)
}
}否则{
//没有有效的目的地,例如移动到区段的最后一行
snapshot.deleteItems([sourceId])
snapshot.appendItems([sourceId],toSection:snapshot.sectionIdentifiers[DestinationIndepath.section])
}
}
应用(快照、动画差异:false、完成:nil)
}
}
如果animatingDifferences
设置为true,它将崩溃(无论如何,这里不需要设置动画)
我不确定是否需要调用
super.tableView(move…
,但它似乎没有任何危害。不幸的是,moveRow和canMove是UITableViewDataSource方法。。。您有关于此功能的一些消息吗?这个答案似乎有一个问题:“if sourceIndexPath.row>destinationIndexPath.row”假设源和目标都在同一节中,这可能不是真的。每个部分都有自己的0…n行编号。注意:编辑此(优秀)答案,以包括在决定快照位置时注意源/目标部分的附加逻辑。moveItem()。如果它适用于任何人,我还将指出:如果将“真实来源”模型数据保留在TableView外部,仅从表视图更改快照并不同时更新模型数据。这是你必须自己做的另一件事。有趣的是,这在iOS 14(Xcode 12.2)上不起作用。需要其他设置吗?例如tableView.isEditing=true
?@通配符,是的,UITableView需要处于编辑模式才能进行单元格重新排序,isEditing=true
。您可能还需要将单元格的编辑模式设置为.none
,我记得这是在tableView:cellforrowatinexpath:
委托方法中完成的。