27563


[![画像の説明をここに入力](https://i.stack.imgur.com/rnvEJ.png)](https://i.stack.imgur.com/rnvEJ.png)カスタムセルをのコレクションビューをドラッグアンドドロップするコードを書きました。  
Swiftのバージョンは2.2です。

やりたいこととしては、ナビゲーションバーの`editButton`を押してから、セルを長押してドラッグアンドドロップしてセルの配列を変更するというものです。

しかしながら、ビルドは通るものの、セルを長押ししても何も反応しませんし動きません。

[code]

    import UIKit
    
    class ViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate {
        var collectionView: UICollectionView?
        var longPressGesture: UILongPressGestureRecognizer?
        var panGesture: UIPanGestureRecognizer?
        var selectedIndexPath: NSIndexPath?
    
        override func viewDidLoad() {
            super.viewDidLoad()
            self.setupSubviews()
            self.autolayoutSubviews()
    
            self.navigationItem.leftBarButtonItem = self.editButtonItem()
        }
    
        func setupSubviews() {
            let flowLayout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
            flowLayout.minimumInteritemSpacing = 10.0
            flowLayout.minimumLineSpacing = 10.0
            flowLayout.sectionInset = UIEdgeInsets(top: 10.0, left: 10.0, bottom: 10.0, right: 10.0)
            flowLayout.itemSize = CGSizeMake(300.0, 100.0)
    
            self.collectionView = UICollectionView(frame: CGRectZero, collectionViewLayout: flowLayout)
            self.collectionView!.translatesAutoresizingMaskIntoConstraints = false
            self.collectionView!.dataSource = self
            self.collectionView!.delegate = self
            self.collectionView!.registerClass(GoodCell.self, forCellWithReuseIdentifier: "GoodCell")
            self.collectionView!.registerClass(BadCell.self, forCellWithReuseIdentifier: "BadCell")
            self.collectionView!.registerClass(TeacherCell.self, forCellWithReuseIdentifier: "TeacherCell")
            self.collectionView!.backgroundColor = UIColor.whiteColor()
            self.view.addSubview(self.collectionView!)
    
            panGesture = UIPanGestureRecognizer(target: self, action: #selector(ViewController.handlePanGesture(_:)))
        //self.panGesture?.enabled = false
        self.collectionView?.addGestureRecognizer(panGesture!)
        //panGesture?.delegate = self
        self.view.addGestureRecognizer(self.panGesture!)
    
        longPressGesture = UILongPressGestureRecognizer(target: self, action: #selector(ViewController.handleLongGesture(_:)))
        longPressGesture?.minimumPressDuration = 0.5
        self.longPressGesture?.enabled = false
        self.collectionView?.addGestureRecognizer(self.longPressGesture!)
        //longPressGesture!.delegate = self
        self.view.addGestureRecognizer(self.longPressGesture!)
        }
    
        func autolayoutSubviews() {    self.collectionView!.topAnchor.constraintEqualToAnchor(self.view.topAnchor).active = true
            self.collectionView!.leadingAnchor.constraintEqualToAnchor(self.view.leadingAnchor).active = true
            self.collectionView!.trailingAnchor.constraintEqualToAnchor(self.view.trailingAnchor).active = true
            self.collectionView!.bottomAnchor.constraintEqualToAnchor(self.view.bottomAnchor).active = true
        }
    
        func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
            return 3
        }
    
        func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
            let cellTypeNumber = indexPath.item % 3
            switch cellTypeNumber {
            case 0:
                let cell1 = collectionView.dequeueReusableCellWithReuseIdentifier("GoodCell", forIndexPath: indexPath) as! GoodCell
                cell1.backgroundColor = UIColor.grayColor()
                return cell1
    
            case 1:
                let cell2 = collectionView.dequeueReusableCellWithReuseIdentifier("BadCell", forIndexPath: indexPath) as! BadCell
                cell2.backgroundColor = UIColor.brownColor()
                return cell2
    
            default:
                let cell3 = collectionView.dequeueReusableCellWithReuseIdentifier("TeacherCell", forIndexPath: indexPath) as! TeacherCell
                cell3.backgroundColor = UIColor.grayColor()
                return cell3
            }
        }
    
        func collectionView(collectionView: UICollectionView, canMoveItemAtIndexPath indexPath: NSIndexPath) -> Bool {
            return true
        }
    
        func collectionView(collectionView: UICollectionView, moveItemAtIndexPath sourceIndexPath: NSIndexPath, toIndexPath destinationIndexPath: NSIndexPath) {
        }
    
        func handleLongGesture(gesture: UILongPressGestureRecognizer) {
            switch (gesture.state) {
            case UIGestureRecognizerState.Began:
                selectedIndexPath = self.collectionView?.indexPathForItemAtPoint(gesture.locationInView(self.collectionView))
            case UIGestureRecognizerState.Changed:
                break
            default:
                selectedIndexPath = nil
            }
        }
    
        func handlePanGesture(gesture: UIPanGestureRecognizer) {
            switch (gesture.state) {
            case UIGestureRecognizerState.Began:
                collectionView?.beginInteractiveMovementForItemAtIndexPath(selectedIndexPath!)
            case UIGestureRecognizerState.Changed:
                collectionView?.updateInteractiveMovementTargetPosition(gesture.locationInView(gesture.view!))
            case UIGestureRecognizerState.Ended:
                collectionView?.endInteractiveMovement()
            default:
                collectionView?.cancelInteractiveMovement()
            }
        }
    
[/code]

func LongGesture(sender: UILongPressGestureRecognizer) {  
print("LongPressed")

[code]

    }
    
    }
    
    extension ViewController: UIGestureRecognizerDelegate {
        func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouledRecognizeSimultaneouslyWithGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool {
            if gestureRecognizer
                == longPressGesture {
                return panGesture
                    == otherGestureRecognizer
            }
            if gestureRecognizer
                == panGesture {
                return longPressGesture == otherGestureRecognizer
            }
            return true
        }
    
        func gestureRecognizerShouldBegin(gestureRecognizer: UIGestureRecognizer) -> Bool {
            guard gestureRecognizer ==
                self.panGesture else {
                    return true
            }
            return selectedIndexPath != nil
        } 
    }
    
[/code]


CC BY-SA 3.0
2016-07-12T06:46:49.687
27559
2016-10-26T01:38:03.350
2016-10-26T01:38:03.350
7256
16775
question
swift
CollectionViewをドラッグアンドドロップするためにUILongPressGestureRecognizerを設定したがロングプレスしても反応がない


ロングプレスのジェスチャが反応しない理由はよおそらく、`UIPanGestureRecognizer`が先に動作してしまっているためだと思います。クラッシュは`handlePanGesture(_:)`メソッドで起こっているので。クラッシュの直接の原因は`handleLongGesture(_:)`が呼ばれてないために`selectedIndexPath`が`nil`のままだからです。

現在のコードにはいろいろと無駄なコードがあるのでそれを削って試してみてください。クラッシュしている`UIPanGestureRecognizer`もセルの移動には必要ありません。

セルの移動は`UICollectionView`の`〜InteractiveMovement()`メソッドが担当してくれるので、`UIPanGestureRecognizer`は不要です。

あと、`UIGestureRecognizerDelegate`は設定していないので、エクステンションも不要です。

さらに、ジェスチャを`collectionView`と`view`の両方に追加していますが、`collectionView`だけでいいです。

不要な部分を除いたコードが下記になります。こちらで試してみてください。

[code]

    import UIKit
    
    class ViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate {
        var collectionView: UICollectionView?
        var longPressGesture: UILongPressGestureRecognizer?
        var selectedIndexPath: NSIndexPath?
    
        override func viewDidLoad() {
            super.viewDidLoad()
            self.setupSubviews()
            self.autolayoutSubviews()
    
            self.navigationItem.leftBarButtonItem = self.editButtonItem()
        }
    
        func setupSubviews() {
            let flowLayout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
            flowLayout.minimumInteritemSpacing = 10.0
            flowLayout.minimumLineSpacing = 10.0
            flowLayout.sectionInset = UIEdgeInsets(top: 10.0, left: 10.0, bottom: 10.0, right: 10.0)
            flowLayout.itemSize = CGSizeMake(300.0, 100.0)
    
            self.collectionView = UICollectionView(frame: CGRectZero, collectionViewLayout: flowLayout)
            self.collectionView!.translatesAutoresizingMaskIntoConstraints = false
            self.collectionView!.dataSource = self
            self.collectionView!.delegate = self
            self.collectionView!.registerClass(GoodCell.self, forCellWithReuseIdentifier: "GoodCell")
            self.collectionView!.registerClass(BadCell.self, forCellWithReuseIdentifier: "BadCell")
            self.collectionView!.registerClass(TeacherCell.self, forCellWithReuseIdentifier: "TeacherCell")
            self.collectionView!.backgroundColor = UIColor.whiteColor()
            self.view.addSubview(self.collectionView!)
    
            longPressGesture = UILongPressGestureRecognizer(target: self, action: #selector(ViewController.handleLongGesture(_:)))
            longPressGesture?.minimumPressDuration = 0.5
            self.longPressGesture?.enabled = false
            self.collectionView?.addGestureRecognizer(self.longPressGesture!)
        }
    
        func autolayoutSubviews() {    self.collectionView!.topAnchor.constraintEqualToAnchor(self.view.topAnchor).active = true
            self.collectionView!.leadingAnchor.constraintEqualToAnchor(self.view.leadingAnchor).active = true
            self.collectionView!.trailingAnchor.constraintEqualToAnchor(self.view.trailingAnchor).active = true
            self.collectionView!.bottomAnchor.constraintEqualToAnchor(self.view.bottomAnchor).active = true
        }
    
        func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
            return 3
        }
    
        func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
            let cellTypeNumber = indexPath.item % 3
            switch cellTypeNumber {
            case 0:
                let cell1 = collectionView.dequeueReusableCellWithReuseIdentifier("GoodCell", forIndexPath: indexPath) as! GoodCell
                cell1.backgroundColor = UIColor.grayColor()
                return cell1
    
            case 1:
                let cell2 = collectionView.dequeueReusableCellWithReuseIdentifier("BadCell", forIndexPath: indexPath) as! BadCell
                cell2.backgroundColor = UIColor.brownColor()
                return cell2
    
            default:
                let cell3 = collectionView.dequeueReusableCellWithReuseIdentifier("TeacherCell", forIndexPath: indexPath) as! TeacherCell
                cell3.backgroundColor = UIColor.grayColor()
                return cell3
            }
        }
    
        func collectionView(collectionView: UICollectionView, moveItemAtIndexPath sourceIndexPath: NSIndexPath, toIndexPath destinationIndexPath: NSIndexPath) {
        }
    
        func handleLongGesture(gesture: UILongPressGestureRecognizer) {
            switch(gesture.state) {
            case UIGestureRecognizerState.Began:
                guard let selectedIndexPath = collectionView?.indexPathForItemAtPoint(gesture.locationInView(collectionView!)) else {
                    break
                }
                collectionView?.beginInteractiveMovementForItemAtIndexPath(selectedIndexPath)
            case UIGestureRecognizerState.Changed:
                collectionView?.updateInteractiveMovementTargetPosition(gesture.locationInView(gesture.view!))
            case UIGestureRecognizerState.Ended:
                collectionView?.endInteractiveMovement()
            default:
                collectionView?.cancelInteractiveMovement()
            }
        }
    }
    
[/code]


CC BY-SA 3.0
2016-07-12T08:32:52.280
27563
2016-07-12T08:32:52.280
5519
27559
answer