Ios UICollectionViewDropDelegate和DiffableDataSource
我试图用DiffableDataSource(在iOS 13中引入)实现Ios UICollectionViewDropDelegate和DiffableDataSource,ios,swift,datasource,Ios,Swift,Datasource,我试图用DiffableDataSource(在iOS 13中引入)实现UICollectionViewDropDelegate 我已经实现了UICollectionViewDragDelegate,它工作得很好 我设置了collectionView.dropDelegate=self 我实现了func collectionView(collectionView:UICollectionView,performDropWith coordinator:UICollectionViewDropC
UICollectionViewDropDelegate
- 我已经实现了
,它工作得很好UICollectionViewDragDelegate
- 我设置了collectionView.dropDelegate=self
- 我实现了
(您甚至可以在方法为空的情况下尝试)func collectionView(collectionView:UICollectionView,performDropWith coordinator:UICollectionViewDropCoordinator)
想法?这是一个相当简单的解决方法。从UICollectionViewDropDelegate函数performDropWith开始。请注意,我只需要一个.move和no.copy,但您只需要添加一个copyItems()方法,类似于下面的reorderItems()方法:
func collectionView(_ collectionView: UICollectionView, performDropWith coordinator: UICollectionViewDropCoordinator) {
var destinationIndexPath: IndexPath
if let indexPath = coordinator.destinationIndexPath {
destinationIndexPath = indexPath
} else {
let section = collectionView.numberOfSections - 1
let row = collectionView.numberOfItems(inSection: section)
destinationIndexPath = IndexPath(row: row, section: section)
}
switch coordinator.proposal.operation {
case .move:
self.reorderItems(coordinator: coordinator, destinationIndexPath: destinationIndexPath, collectionView: collectionView)
break
case .copy:
// Not copying between collections so this block not needed.
return
default:
return
}
}
然后我们使用函数reorderItems()来处理collectionView中的实际更改。需要明确的一点是,快照(NSDiffableDataSourceSnapshot)和数据源(UICollectionViewDiffableDataSource)都是类变量
/// reorderItems method
/// This method moves a cell from the sourceIndexPath to the destinationIndexPath within the same UICollectionView
///
/// - Parameters:
/// - coordinator: UICollectionViewDropCoordinator obtained in performDropWith
/// - destinationIndexPath: IndexPath where user dropped the element.
/// - collectionView: UICollectionView object where reordering is done.
private func reorderItems(coordinator: UICollectionViewDropCoordinator, destinationIndexPath: IndexPath, collectionView: UICollectionView) {
let items = coordinator.items
if items.count == 1, let item = items.first, let sourceIndexPath = item.sourceIndexPath {
var destIndexPath = destinationIndexPath
if destIndexPath.row >= collectionView.numberOfItems(inSection: destIndexPath.section) {
destIndexPath.row = collectionView.numberOfItems(inSection: destIndexPath.section) - 1
}
/// Since my collectionView data is attributed to a Firebase.storage set of data, this is where I write my changes back to the store.
snapshot.moveItem(dataSource.itemIdentifier(for: sourceIndexPath)!, beforeItem: dataSource.itemIdentifier(for: destinationIndexPath)!)
dataSource.apply(snapshot, animatingDifference: true)
coordinator.drop(items.first!.dragItem, toItemAt: destIndexPath)
}
}
这是一个相当容易解决的问题。从UICollectionViewDropDelegate函数performDropWith开始。请注意,我只需要一个.move和no.copy,但您只需要添加一个copyItems()方法,类似于下面的reorderItems()方法:
func collectionView(_ collectionView: UICollectionView, performDropWith coordinator: UICollectionViewDropCoordinator) {
var destinationIndexPath: IndexPath
if let indexPath = coordinator.destinationIndexPath {
destinationIndexPath = indexPath
} else {
let section = collectionView.numberOfSections - 1
let row = collectionView.numberOfItems(inSection: section)
destinationIndexPath = IndexPath(row: row, section: section)
}
switch coordinator.proposal.operation {
case .move:
self.reorderItems(coordinator: coordinator, destinationIndexPath: destinationIndexPath, collectionView: collectionView)
break
case .copy:
// Not copying between collections so this block not needed.
return
default:
return
}
}
然后我们使用函数reorderItems()来处理collectionView中的实际更改。需要明确的一点是,快照(NSDiffableDataSourceSnapshot)和数据源(UICollectionViewDiffableDataSource)都是类变量
/// reorderItems method
/// This method moves a cell from the sourceIndexPath to the destinationIndexPath within the same UICollectionView
///
/// - Parameters:
/// - coordinator: UICollectionViewDropCoordinator obtained in performDropWith
/// - destinationIndexPath: IndexPath where user dropped the element.
/// - collectionView: UICollectionView object where reordering is done.
private func reorderItems(coordinator: UICollectionViewDropCoordinator, destinationIndexPath: IndexPath, collectionView: UICollectionView) {
let items = coordinator.items
if items.count == 1, let item = items.first, let sourceIndexPath = item.sourceIndexPath {
var destIndexPath = destinationIndexPath
if destIndexPath.row >= collectionView.numberOfItems(inSection: destIndexPath.section) {
destIndexPath.row = collectionView.numberOfItems(inSection: destIndexPath.section) - 1
}
/// Since my collectionView data is attributed to a Firebase.storage set of data, this is where I write my changes back to the store.
snapshot.moveItem(dataSource.itemIdentifier(for: sourceIndexPath)!, beforeItem: dataSource.itemIdentifier(for: destinationIndexPath)!)
dataSource.apply(snapshot, animatingDifference: true)
coordinator.drop(items.first!.dragItem, toItemAt: destIndexPath)
}
}
如果您正在使用collectionView.PerformBatChUpdate()进行更改以更新collectionView,则此操作将崩溃,您似乎需要在数据源(UICollectionViewDiffableDataSource)上运行快照,正如您所看到的,错误中指出:“当充当UICollectionView的数据源时,UICollectionViewDiffableDataSource API:请不要直接在UICollectionView上调用变异API” 试试这个:
// MARK: - Properties
var dataSource: UICollectionViewDiffableDataSource<Int, UIImage>?
var entry: Entry? {
didSet {
guard let entry = entry else { return }
let dateFormatter = DateFormatter()
dateFormatter.setLocalizedDateFormatFromTemplate("MMM dd yyyy, hh:mm")
title = dateFormatter.string(from: entry.dateCreated)
}
}
而重新加载快照是:
private func reloadSnapshot(animated: Bool) {
var snapshot = NSDiffableDataSourceSnapshot<Int, UIImage>()
snapshot.appendSections([0])
snapshot.appendItems(entry?.images ?? [])
dataSource?.apply(snapshot, animatingDifferences: animated)
}
如果您正在更改collectionView.PerformBatchUpdate()以更新您的collectionView,这将崩溃,似乎您需要在您的数据源(UICollectionViewDiffableDataSource)上使用快照正如您所看到的,错误中指出:“当充当UICollectionView的数据源时,UICollectionViewDiffableDataSource API:请不要直接在UICollectionView上调用变异API” 试试这个:
// MARK: - Properties
var dataSource: UICollectionViewDiffableDataSource<Int, UIImage>?
var entry: Entry? {
didSet {
guard let entry = entry else { return }
let dateFormatter = DateFormatter()
dateFormatter.setLocalizedDateFormatFromTemplate("MMM dd yyyy, hh:mm")
title = dateFormatter.string(from: entry.dateCreated)
}
}
而重新加载快照是:
private func reloadSnapshot(animated: Bool) {
var snapshot = NSDiffableDataSourceSnapshot<Int, UIImage>()
snapshot.appendSections([0])
snapshot.appendItems(entry?.images ?? [])
dataSource?.apply(snapshot, animatingDifferences: animated)
}
所有这些都是基于raywenderlich.com“Catalyst by Tutorials”的阅读和工作
如果您正在使用UICollectionViewDropDelegate
方法返回UICollectionViewDropProposal
,collectionView(\uuuU9:dropSessionDidUpdate:WithDestinationIndepath DestinationIndepath:)
,此方法将在设置放置动画时调用引擎盖下的不可扩散方法
我的猜测是,苹果从未将其与分散数据源一起测试过。您需要删除此方法,并以不同的方式自行实现其动画。还有一件事:
如果您正在使用UICollectionViewDropDelegate
方法返回UICollectionViewDropProposal
,collectionView(\uuuU9:dropSessionDidUpdate:WithDestinationIndepath DestinationIndepath:)
,此方法将在设置放置动画时调用引擎盖下的不可扩散方法
我的猜测是,苹果从未将其与可扩散数据源一起测试过。你需要删除此方法,并以不同的方式自己实现其动画。它们可能真的不兼容。在我看来,关于可扩散数据源的很多问题都没有经过很好的思考。你有没有设法解决过这个问题?我有点担心同一个now@matt我想他们只是忘记了拖放。合成版面也不太支持它。它们可能真的不兼容。在我看来,有很多关于分散数据源的问题没有经过深思熟虑。你有没有解决过这个问题?我也有同样的问题now@matt我想他们只是rgot关于拖放。合成版面也不太支持它。