ios - 无法将 CollectionViewCell 移动到末尾

标签 ios swift uicollectionview uigesturerecognizer

我在 UIViewController 中有一个 UICollectionView。我配置了一个手势识别器来移动单元格。它适用于将单元格移动到除末尾以外的任何索引。最令人恼火的是,当我尝试将单元格移动到末尾时,应用程序不会崩溃——它只是挂起。我可以退出 ReorderViewController 并返回它。 View 会正常重新加载。

我从 viewDidLoad 调用这个方法来配置手势识别器:

func configureGestureRecognizer() {
    // configure longPressGestureRecognizer
    longPressGesture = UILongPressGestureRecognizer(target: self, action: #selector(ReorderViewController.handleLongPressGesture))
    longPressGesture.minimumPressDuration = 0.5
    longPressGesture.delegate = self
    self.collectionView.addGestureRecognizer(longPressGesture)
}

UILongPressGestureRecognizer 被触发时,它的处理程序被调用:

func handleLongPressGesture(gesture: UILongPressGestureRecognizer) {
    guard let selectedIndexPath = self.collectionView.indexPathForItem(at: gesture.location(in: self.collectionView)) else {
        return
    }
    let selectedCell = collectionView.cellForItem(at: selectedIndexPath)

    switch gesture.state {
    case .began:
        print("began")
        editMode = true
        collectionView.beginInteractiveMovementForItem(at: selectedIndexPath)
        selectedCell?.isSelected = true
    case .changed:
        editMode = true
        selectedCell?.isSelected = true
        print("changed")
        collectionView.updateInteractiveMovementTargetPosition(gesture.location(in: self.collectionView))
    case .ended:
        print("ended")
        editMode = false
        selectedCell?.isSelected = false
        collectionView.endInteractiveMovement()
    default:
        print("default")
        editMode = false
        selectedCell?.isSelected = false
        collectionView.cancelInteractiveMovement()
    }
}

我可以毫无困难地使用手势移动单元格,只要我不将一个单元格移动到末尾即可。最烦人的是,应用程序不会崩溃——它只是挂起。我可以按 NavBar 上的“后退”按钮并转到之前的 ViewController 而不会崩溃并返回到 ReorderViewController。

这是我移动单元格的代码:

func collectionView(_ collectionView: UICollectionView, moveItemAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
    let stuffToReorder = currentRoutine?.myOrderedSet.mutableCopy() as! NSMutableOrderedSet
    stuffToReorder.exchangeObject(at: sourceIndexPath.row, withObjectAt: destinationIndexPath.row)
    currentRoutine?.myOrderedSet = stuffToReorder as NSOrderedSet
    appDelegate.saveContext()
}

非常感谢任何关于我的错误的想法。

最佳答案

我想我已经破解了它。我对 CoreData 问题的直觉是转移注意力(这也是我对它没有太多经验的原因!)。挂断是由处理程序方法开头的 guard 语句引起的。具体来说,您的方法检查是否存在与手势位置相关的有效索引路径;如果手势移出 Collection View ,我认为一切都会变得困惑,因此您会挂起(而不是崩溃),因为函数会在该点继续退出。然而,稍作调整似乎可以解决问题:

    func handleLongPressGesture(gesture: UILongPressGestureRecognizer) {
        guard let _ = collectionVC.collectionView else { return }

        switch gesture.state {
        case .began:
            guard let selectedIndexPath = collectionVC.collectionView!.indexPathForItem(at: gesture.location(in: collectionVC.collectionView)) else { return }
            selectedCell = collectionVC.collectionView!.cellForItem(at: selectedIndexPath)
            print("began")
            lastGoodLocation = gesture.location(in: collectionVC.collectionView!)
            collectionVC.collectionView!.beginInteractiveMovementForItem(at: selectedIndexPath)
        selectedCell.isSelected = true

        case .changed:

            selectedCell?.isSelected = true
            if collectionVC.collectionView!.frame.contains(gesture.location(in: view)) {
                print(gesture.location(in: view))
                print(collectionVC.collectionView!.frame)
                print("INSIDE COLLECTION VIEW!")
                collectionVC.collectionView!.updateInteractiveMovementTargetPosition(gesture.location(in: collectionVC.collectionView!))
                lastGoodLocation = gesture.location(in: collectionVC.collectionView!)
            }
            else
            {
                print("OUTSIDE COLLECTION VIEW!")
                collectionVC.collectionView!.updateInteractiveMovementTargetPosition(lastGoodLocation) // Not sure this is needed
            }
            print("changed")

        case .ended:
            print("ended")

            selectedCell?.isSelected = false
            collectionVC.collectionView!.endInteractiveMovement()

        default:
            print("default")

            selectedCell?.isSelected = false
            collectionVC.collectionView!.cancelInteractiveMovement()
        }
    }

以这种方式实现,我将 selectedCell 的 guard 语句移到了 switch 的 .began 案例中,因为这是它唯一被初始化的地方。因此,我必须将 selectedCell 声明为类属性,以便稍后在其他情况下可以引用它。我还引入了一个 CGPoint 变量 lastGoodLocation,它存储有效索引路径可用的最后一个位置 - 这样,如果手势在 Collection View 之外结束,单元格将发送到该索引路径。

无论如何,这有点粗糙,但肯定可以防止挂起。希望对您有所帮助!

关于ios - 无法将 CollectionViewCell 移动到末尾,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40137103/

相关文章:

swift - Alamofire 错误始终为零,而请求失败

swift - 如何使用 Firebase 更新 CollectionView 模型?

ios - UICollectionView - 一次一个 Cell 的水平分页

ios - 我可以使用 apn_on_rails 推送报亭通知吗?

ios - `window.close`被 `webView.uiDelegate`打开后如何处理?

iphone - 快门动画上方的 cameraOverlayView

swift - 将 Internet url 加载到 Webview

ios - 在不同设备上动态设置 Collection View 单元格大小

桌面 Safari 的“开发”菜单中缺少带有 iOS11 (Xcode 9) 设备的 iOS 模拟器

ios - 如何在 CGRectMake 函数中使用变量 - 尝试以表格结构输出数据