gpt4 book ai didi

ios - UICollectionViewDropDelegate 和 DiffableDataSource

转载 作者:行者123 更新时间:2023-12-04 12:59:52 24 4
gpt4 key购买 nike

我正在尝试实现 UICollectionViewDropDelegate使用 DiffableDataSource(在 iOS 13 中引入)。

  • 我已经实现 UICollectionViewDragDelegate ,这很好用。
  • 我设置了collectionView.dropDelegate = self
  • 我实现了 func collectionView(_ collectionView: UICollectionView, performDropWith coordinator: UICollectionViewDropCoordinator) (你甚至可以在方法为空的情况下尝试)。

  • 该应用程序将构建并运行,但是一旦您开始拖动单元格,该应用程序立即崩溃并显示以下消息:

    Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'UICollectionView must be updated via the UICollectionViewDiffableDataSource APIs when acting as the UICollectionView's dataSource: please do not call mutation APIs directly on UICollectionView.



    所以看起来这个方法试图直接修改 UICollectionView (也许在你移动项目时移动单元格?)我不知道如何绕过这种行为。

    想法?

    最佳答案

    这是一个相当容易的解决方案。从 UICollectionViewDropDelegate 函数 performDropWith 开始。请注意,我只需要一个 .move 而不需要 .copy ,但您只需添加一个类似于下面的 reorderItems() 方法的 copyItems() 方法:

    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)
    }
    }

    关于ios - UICollectionViewDropDelegate 和 DiffableDataSource,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59699679/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com