gpt4 book ai didi

ios - 使用 UICollectionViewDiffableDataSource 和 NSFetchedResultsController 重新排序单元格

转载 作者:行者123 更新时间:2023-12-01 15:28:42 25 4
gpt4 key购买 nike

我正在使用 UICollectionViewDiffableDataSource和一个 NSFetchedResultsController填充我的 UICollectionView在我的 UIViewController .

为了添加重新排序单元格的能力,我添加了一个 UILongPressGestureRecognizer和子类 UICollectionViewDiffableDataSource为了使用它是canMoveItemAt:moveItemAt:方法。

对单元格重新排序时,会发生以下情况:

  • moveItemAt:被调用,我更新对象位置属性并保存 MOC
  • controllerDidChangeContent:NSFetchedResultsControllerDelegate被调用,我从当前的 fetchedObjects 创建一个新快照并应用它。

  • 当我申请时 dataSource?.apply(snapshot, animatingDifferences: true)细胞立即转换位置。如果我设置 animatingDifferences: false它有效,但所有单元格都重新加载 明显 .

    这里有什么最佳实践,如何在 UICollectionViewDiffableDataSource 上实现单元格重新排序?和一个 NSFetchedResultsController ?

    以下是我提到的方法:

    // ViewController 
    func createSnapshot(animated: Bool = true) {
    var snapshot = NSDiffableDataSourceSnapshot<Int, Favorite>()
    snapshot.appendSections([0])
    snapshot.appendItems(provider.fetchedResultsController.fetchedObjects ?? [])
    dataSource?.apply(snapshot, animatingDifferences: animated)
    }

    // NSFetchedResultsControllerDelegate
    func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
    createSnapshot(animated: false)
    }

    // Subclassed UICollectionViewDiffableDataSource
    override func collectionView(_ collectionView: UICollectionView, moveItemAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
    provider.moveFavorite(from: sourceIndexPath.row, to: destinationIndexPath.row)
    }

    // Actual cell moving in a provider class
    public func moveFavorite(from source: Int, to destination: Int) {
    guard let favorites = fetchedResultsController.fetchedObjects else { return }
    if source < destination {
    let partialObjects = favorites.filter({ $0.position <= destination && $0.position >= source })

    for object in partialObjects {
    object.position -= 1
    }

    let movedFavorite = partialObjects.first
    movedFavorite?.position = Int64(destination)
    }
    else {
    let partialObjects = favorites.filter({ $0.position >= destination && $0.position <= source })

    for object in partialObjects {
    object.position += 1
    }

    let movedFavorite = partialObjects.last
    movedFavorite?.position = Int64(destination)
    }
    do {
    try coreDataHandler.mainContext.save()
    } catch let error as NSError {
    print(error.localizedDescription)
    }
    }

    最佳答案

    我对同一问题的解决方案是将 UICollectionViewDiffableDataSource 子类化并在子类中实现 canMoveItemAt 方法以回答 true。
    如果 .ended 的 longPressAction 案例做了三件事,动画似乎对我来说很好用:

  • 更新模型
  • 调用 dateSource.collectionView(..moveItemAt:..)
  • 运行您的 dataSource.apply

  • 其他常见的拖动行为方法也必须实现,看起来你已经完成了。仅供引用 - 这些方法在 UICollectionView 的“以交互方式重新排序项目”部分中有详细记录。 https://developer.apple.com/documentation/uikit/uicollectionview
    class PGLDiffableDataSource: UICollectionViewDiffableDataSource<Int, Int> {
    override func collectionView(_ collectionView: UICollectionView, canMoveItemAt indexPath: IndexPath) -> Bool {
    return true
    }

    }

    关于ios - 使用 UICollectionViewDiffableDataSource 和 NSFetchedResultsController 重新排序单元格,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58029290/

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