我在UICollectionView
中有一个UIViewController
。我配置了一个手势识别器来移动单元格。它适用于将单元格移动到除结尾之外的任何索引。最令人沮丧的是,当我试图将一个单元移动到最后时,应用程序并没有崩溃 - 它只是挂起。我可以退出ReorderViewController
并回到它。视图正常重新加载。
我从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()
}
任何想法:非常感谢我的错误。
答案 0 :(得分:2)
我想我已经破解了它。关于CoreData问题的预感是一个红色的鲱鱼(就像我对它没有多少经验一样好!)。挂断是由处理程序方法开始时的guard语句引起的。具体来说,您的方法检查是否存在与手势位置相关的有效索引路径;如果手势移出集合视图,我认为所有事情都会混淆,因此你会在该点停止退出时(而不是崩溃)。然而,移动一些东西似乎解决了这个问题:
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,它存储了一个有效索引路径可用的最后位置 - 这样,如果手势在集合视图之外结束,则该单元被发送到该索引路径。
无论如何,这有点粗糙,但肯定似乎可以防止挂起。希望有所帮助!