`dropSessionDidUpdate` 中的 UICollectionViewDropDelegate 错误的目标索引路径

Posted

技术标签:

【中文标题】`dropSessionDidUpdate` 中的 UICollectionViewDropDelegate 错误的目标索引路径【英文标题】:UICollectionViewDropDelegate wrong destination index path in `dropSessionDidUpdate` 【发布时间】:2020-01-22 02:12:26 【问题描述】:

我正在尝试在这个狭长的集合视图中实现拖放:

它具有水平布局,具有不同大小的单元格和部分。

拖动交互效果很好,但是我注意到UICollectionViewDropDelegate有一个问题:

func collectionView(
    _ collectionView: UICollectionView,
    dropSessionDidUpdate session: UIDropSession,
    withDestinationIndexPath destinationIndexPath: IndexPath?)
    -> UICollectionViewDropProposal 

    if let destination = destinationIndexPath 
        print(destination) // Prints WRONG index path!!!
        return UICollectionViewDropProposal(
            operation: .move, intent: .insertAtDestinationIndexPath
        )
    

    return UICollectionViewDropProposal(
        operation: .cancel, intent: .unspecified
    )

错误的目标索引路径被传递给collectionView(_:dropSessionDidUpdate:withDestinationIndexPath:)。 因此,我无法正确确定该部分并确定该部分是否可用。

【问题讨论】:

【参考方案1】:

所以,这是 UIKit 的一个错误。正确的目的索引路径可以计算如下:

func collectionView(
    _ collectionView: UICollectionView,
    dropSessionDidUpdate session: UIDropSession,
    withDestinationIndexPath destinationIndexPath: IndexPath?)
    -> UICollectionViewDropProposal 

    // Calculating location in view
    let location = session.location(in: collectionView)
    var correctDestination: IndexPath?

    // Calculate index inside performUsingPresentationValues
    collectionView.performUsingPresentationValues 
        correctDestination = collectionView.indexPathForItem(at: location)
    

    guard let destination = correctDestination else 
        return UICollectionViewDropProposal(
            operation: .cancel, intent: .unspecified
        )
    

    // check destination 
    // ...

为了修复这个错误,我首先尝试使用location(in:)indexPathForItem(at:) 的组合。结果索引路径等于委托方法提供的destinationIndexPath。为什么? UIDataSourceTranslating 引起了我的注意。这是一个协议,允许集合和表格视图显示用于拖放的占位符单元格,而无需更改实际数据源。当拖放交互结束时,占位符很容易被删除。所以,我做了一个假设,

    destinationIndexPath 是在 indexPathForItem(at:) 的帮助下计算的 它会忽略 UIDataSourceTranslating 创建的占位符,这是一个错误

然后我尝试将indexPathForItem(at:)包装成performUsingPresentationValues(_:),收到的索引路径是正确的!

【讨论】:

我向 Apple 报告了该错误 (FB7290341)。 不幸的是,这种变通办法每两次都会给出错误的索引。如果我快速拖动到不可见的部分,我会得到上一部分的索引路径。试图禁用预取并设置collectionView.reorderingCadence = .slow — 没有任何帮助。是否有可能以某种方式模仿延迟? @AlexeyChekanov,1)我不知道如何帮助您,最好针对您的特定收藏视图提出特定的问题,因为我没有这样的问题。 2)你在跟踪我吗?你最近回答了我的另一个问题。 不,我没有关注。只是巧合 :-) 可能我们都在处理相同的集合视图问题。

以上是关于`dropSessionDidUpdate` 中的 UICollectionViewDropDelegate 错误的目标索引路径的主要内容,如果未能解决你的问题,请参考以下文章

如何用ruby中的数组中的元素替换字符串中的单词?

如何将视图中的 javascript 代码中的对象列表传递给控制器​​中的操作方法

如何从账户 A 中的 Lambda(VPC 中的 Lambda)调用账户 B 中的 AWS Lambda 函数(VPC 中的这个 Lambda)

我可以在 apatch 中的 php 文件中播放位于硬盘中的文件路径中的视频吗?

子窗口访问父页面iframe中的iframe,top打开的子窗口访问父页面中的iframe中的iframe

为啥正文中的 javascript 函数优先于头部中的函数?