27553


現在、CollectionViewをDrag and Dropさせるプログラムをswift2.2で書いています。

しかし、ビルドは通るものの、セルを長押しするとsignal SIGABRTのエラーが出てしまいます。  
様々なサイトを拝見してみたのですが、解決方法が未だわかりません。  
何方か解決方法をご教示いただけないでしょうか。

[code]

    import UIKit
    
    class ViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate {
    
        var collectionView: UICollectionView?
        var longPressGesture: UILongPressGestureRecognizer?
        var panGesture: UIPanGestureRecognizer?
        var selectedIndexPath: NSIndexPath?
    
        required init?(coder aDecoder: NSCoder) {
            super.init(coder: aDecoder)
        }
    
        override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
        super.init(nibName: nil, bundle: nil)
        }
    
        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: "handlePanGesture:")
            self.collectionView?.addGestureRecognizer(panGesture!)
            //panGesture?.delegate = self
            self.collectionView!.addGestureRecognizer(self.panGesture!)
    
            longPressGesture = UILongPressGestureRecognizer(target: self, action: Selector("handleLongGesture"))
            longPressGesture!.minimumPressDuration = 0.5
            self.collectionView?.addGestureRecognizer(longPressGesture!)
            //longPressGesture.delegate = self
            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, 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()
            }
        }
    }
    
    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]

エラー↓

[code]

    *** First throw call stack:
    (
        0   CoreFoundation                      0x002c5494 __exceptionPreprocess + 180
        1   libobjc.A.dylib                     0x01fd9e02 objc_exception_throw + 50
        2   CoreFoundation                      0x002cf253 -[NSObject(NSObject) doesNotRecognizeSelector:] + 275
        3   CoreFoundation                      0x0020489d ___forwarding___ + 1037
        4   CoreFoundation                      0x0020446e _CF_forwarding_prep_0 + 14
        5   UIKit                               0x0104cd04 _UIGestureRecognizerSendTargetActions + 168
        6   UIKit                               0x01048bc2 _UIGestureRecognizerSendActions + 176
        7   UIKit                               0x010466c0 -[UIGestureRecognizer _updateGestureWithEvent:buttonEvent:] + 929
        8   UIKit                               0x010493b3 -[UIGestureRecognizer _delayedUpdateGesture] + 60
        9   UIKit                               0x0104fcfc ___UIGestureRecognizerUpdate_block_invoke898 + 86
        10  UIKit                               0x0104fb69 _UIGestureRecognizerRemoveObjectsFromArrayAndApplyBlocks + 374
        11  UIKit                               0x0103a8a2 _UIGestureRecognizerUpdate + 3407
        12  CoreFoundation                      0x001d775e __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 30
        13  CoreFoundation                      0x001d76be __CFRunLoopDoObservers + 398
        14  CoreFoundation                      0x001cd03c __CFRunLoopRun + 1340
        15  CoreFoundation                      0x001cc846 CFRunLoopRunSpecific + 470
        16  CoreFoundation                      0x001cc65b CFRunLoopRunInMode + 123
        17  GraphicsServices                    0x0479b664 GSEventRunModal + 192
        18  GraphicsServices                    0x0479b4a1 GSEventRun + 104
        19  UIKit                               0x00ab3eb9 UIApplicationMain + 160
        20  DraggingObject                      0x000bebe1 main + 145
        21  libdyld.dylib                       0x029f0a25 start + 1
    )
    libc++abi.dylib: terminating with uncaught exception of type NSException
    (lldb) 
    
[/code]


CC BY-SA 3.0
2016-07-11T10:50:34.190
27533
2016-10-26T01:37:13.843
2016-10-26T01:37:13.843
7256
16775
question
swift
CollectionViewをドラッグアンドドロップさせる方法


`UILongPressGestureRecognizer`に指定しているメソッドの名前が間違っています。

[code]

    longPressGesture = UILongPressGestureRecognizer(target: self,
                                                    action: Selector("handleLongGesture"))
    
[/code]

`func handleLongGesture(gesture:
UILongPressGestureRecognizer)`はパラメータを一つ取るので、`Selector("handleLongGesture:")`のようにコロン「`:`」が必要になります。コロンを付けない場合は、引数なしの`func
handleLongGesture()`のようなメソッドを表します。

なお、`Selector`は`StringLiteralConvertible`なのでそのまま文字列リテラルを使って、

[code]

    UILongPressGestureRecognizer(target: self,
                                 action: "handleLongGesture:")
    
[/code]

のように書け、さらにSwift 2.2ではセレクタを表すリテラル表記が導入されたので、

[code]

    UILongPressGestureRecognizer(target: self,
                                 action: #selector(ViewController.handleLongGesture(_:))
    
[/code]

上記のように`#selector(...)`という形で書けます。セレクタのリテラル表記を使うと、メソッド名を間違えて存在しないメソッドを指定した場合にはコンパイルエラーになるので、このような実行時エラーを防げます。


CC BY-SA 3.0
2016-07-12T04:43:11.663
27553
2016-07-12T04:43:11.663
5519
27533
answer