ios - 拖放 UICollectionView 单元格重用问题

标签 ios swift uicollectionview drag-and-drop

所以我为我的 UICollectionView 实现了拖放,如下所示:

func collectionView(_ collectionView: UICollectionView, itemsForBeginning session: UIDragSession, at indexPath: IndexPath) -> [UIDragItem] {
        guard shouldAllowDragForIndexPath?(indexPath) == true else { return [] }
        guard let cell = collectionView.cellForItem(at: indexPath)?.toImage() else {
            return []
        }
        let provider = NSItemProvider(object: cell)
        let item = UIDragItem(itemProvider: provider)
        item.localObject = data[indexPath.row]

        return [item]
    }

    func collectionView(_ collectionView: UICollectionView, performDropWith coordinator: UICollectionViewDropCoordinator) {
        guard
            let item = coordinator.items.first?.dragItem,
            let sourceIndexPath = coordinator.items.first?.sourceIndexPath,
            let destinationIndexPath = coordinator.destinationIndexPath,
            let entity = item.localObject as? T
            else {
                return
        }
        collectionView.performBatchUpdates({ [unowned self] in
            dropEntityAtIndexPath?(entity, destinationIndexPath)
            self.collectionView.deleteItems(at: [sourceIndexPath])
            self.collectionView.insertItems(at: [destinationIndexPath])
        }, completion: nil)
        coordinator.drop(item, toItemAt: destinationIndexPath)
        item.localObject = nil
    }

    func collectionView(_ collectionView: UICollectionView, dropSessionDidUpdate session: UIDropSession, withDestinationIndexPath destinationIndexPath: IndexPath?) -> UICollectionViewDropProposal {
        if
            session.localDragSession != nil,
            let path = destinationIndexPath,
            shouldAllowDropForIndexPath?(path) == true {
            return UICollectionViewDropProposal(operation: .move, intent: .insertAtDestinationIndexPath)
        } else {
            return UICollectionViewDropProposal(operation: .forbidden)
        }
    }

一切正常,但当电池被重复使用时我发现了奇怪的行为。 这是视频:link

所以它只发生在单元格被拖动之后,而且似乎有一些灰色的覆盖 View ,但我在 View 调试器上看不到它。另外,我尝试在 prepareForReuse 中设置单元格的 imageView.image = nil 但没有帮助。如果有人帮助我解决这个问题,我将非常感激。谢谢。

Edit1:cellForItemAt中的代码:

override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(for: indexPath, cellType: PhotoCollectionViewCell.self)
        let container = data[indexPath.row].postContainer,
        let post = container.postMedia.first
        let isCarousel = container.isCarousel
        let isVideo = post.isVideo
        let _isSelected = isSelected?(indexPath) ?? false
        let url = post.thumbURL?.toURL()
        let isScheduled = container.schedulerFor != nil
        let fromInstagram = false

        cell.configure(url: url, isSelected: _isSelected, isVideo: isVideo, isCarousel: isCarousel, isScheduled: isScheduled, fromInstagram: fromInstagram)

    return cell
}

编辑2 小区配置功能:

func configure(url: URL?, isSelected: Bool = false, isVideo: Bool = false, isCarousel: Bool = false, isScheduled: Bool = false, fromInstagram: Bool = false) {
        checkmarkImageView.isHidden = !isSelected
        selectionOverlay.isHidden = !isSelected
        isVideoImageView.isHidden = !isVideo
        carouselImageView.isHidden = !isCarousel
        cornerImageView.image = isScheduled ? R.image.cyanCorner() : R.image.grayCorner()
        instagramImageView.isHidden = !fromInstagram
        cornerImageView.isHidden = fromInstagram
        url.map(imageView.setImage(with:))
    }

最佳答案

我认为问题不是单元重用,而是模型更新不当。 item.localData移动完成后应正确更新。

这意味着您必须在调用 UICollectionView 之前更新数据模型对象更新。

这是 UICollectionViewDelegate 的示例,但只有这些行真正重要:

// YOUR MODEL OBJECT is expected to be a list-like data structure
YOUR_MODEL_OBJECT.insert(YOUR_MODEL_OBJECT.remove(at: sourceIndex), at: destinationIndex)

UICollectionViewDelegate 的工作原理

func collectionView(_ collectionView: UICollectionView, moveItemAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
    guard destinationIndexPath != sourceIndexPath else { return }
    // YOUR MODEL OBJECT is expected to be a list-like data structure
    YOUR_MODEL_OBJECT.insert(YOUR_MODEL_OBJECT.remove(at: sourceIndex), at: destinationIndex)
}

关于ios - 拖放 UICollectionView 单元格重用问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60479179/

相关文章:

ios - 从 JSON 中一张一张加载照片

arrays - Swift:无法将项目附加到具有两个值的数组

ios - 快速 editActionsForRowAtIndexPath

ios - 避免 UIImageView 在不同设备上拉伸(stretch)

ios - FaSTLane车道上传应用到testflight

ios - 如何以编程方式显示/推送导航 Controller

ios - iOS 8 (Swift) 上基于网格的 UICollectionView

ios - 使用 iOS 7.1 从 UICollectionViewController 进行推送转换时 UINavigationBar 后面的深色背景

iOS: Storyboard CollectionView segue 未被触发

android - React Native 输出是 .class(对于 android)和 .c(对于 iOS)