2016-10-19 7 views
1

私はUIViewControllerUICollectionViewを持っています。私はジェスチャ認識プログラムを設定して細胞を移動させました。それは、端を除く任意のインデックスにセルを移動するために正常に動作します。私が最後にセルを移動しようとすると、最も重大なことに、アプリケーションはクラッシュしません - それはちょうどハングアップします。私はReorderViewControllerから戻ってそれに戻ることができます。ビューは正常にリロードされます。問題の移動CollectionViewCellを最後に

私はジェスチャー認識を設定するには、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

こんにちはアドリアン - 私は(50イントを含むNSOrderedセットを使用して)遊び場で上記を再現しました。あなたのコードでは問題ありませんが、ここでNSOrderedSetを使用している特別な理由はありませんか?私が再作成できないのは、currentRoutineへの参照だけでなく、appDelegate.saveContext呼び出しで少しぼんやりとしています。これらが何であるか、プロジェクトでの役割についてもう少し詳しく説明できますか? – Sparky

+0

@ Sparky見てくれてありがとう! 'currentRoutine'はNSManagedObjectsのNSOrderedSetです。私は物理的なデバイスでそれを試して、私はそこにバグを複製することができます。 「フリーズ」は、オブジェクトを他のセルの範囲を超えてドラッグすると発生します。 'appDelegate.saveContext()'コールは、 'myOrderedSet'の順序が変更されたときにNSManagedObjectを保存することです。 – Adrian

答えて

2

私はそれをクラックしたと思います。 CoreDataが問題になっていることについての私の勘違いは、私にはあまり経験がないだけでなく、ちょうどいいです!ハングアップは、ハンドラーメソッドの開始時にガードステートメントによって引き起こされました。具体的には、ジェスチャの場所に関連する有効なインデックスパスがあるかどうかをチェックします。ジェスチャーがコレクションビューから外れた場合、私はすべてが混乱していると思うので、関数がその時点で終了するので、ハング(クラッシュではなく)を取得します。少し周りのものを移動する、しかし、問題は解決しているようだ:これが唯一の場所であるよう

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() 
     } 
    } 

物事をこのように実装し、私は、あなたのスイッチの.began場合にselectedCellためのガード文を移動していることを初期化されます。したがって、後で他のケースでも参照できるように、selectedCellをクラスプロパティとして宣言しなければなりませんでした。また、CGPoint変数lastGoodLocationを導入しました。これは、有効なインデックスパスが使用可能な最後の場所を格納します。この方法で、ジェスチャがコレクションビューの外側で終了すると、そのインデックスパスにセルが送られます。

とにかく、これはやや粗いですが、確かにハングを防ぐようです。希望が助けてくれる!

+0

ありがとうございました!それだった!私は 'var lastGoodLocation:CGPoint? 'をクラスの先頭に宣言しました。それから、 'case .changed:'を 'if-else'に変更しました。非常に簡単な解決策。家にいる人たちのために、私は 'case.changed:'で 'selectedCell?.SSelected = true'を取り出したので、ユーザーがドラッグするすべてのセルも選択されません。 – Adrian

関連する問題