43225


`#selector(ViewController.drawGesture(_:)))`の箇所で

Type 'ViewController' has no member 'drawGesture' エラーになります。  
下記にfuncはあるのですがどこが悪いか教えて戴けませんか。

[code]

    func drawGesture(sender: AnyObject) {
    
[/code]

構文の概要

[code]

    import UIKit
    
    class ViewController: UIViewController, UIScrollViewDelegate {  //UIScrollViewDelegateを追加
    
        @IBOutlet weak var scrollView: UIScrollView!
        @IBOutlet weak var canvasView: UIImageView!
        @IBOutlet weak var sliderValue: UISlider!
    
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
        }
    
        override func didReceiveMemoryWarning() {
            super.didReceiveMemoryWarning()
            // Dispose of any resources that can be recreated.
        }
    
        private func prepareDrawing() {
    
            //実際のお絵描きで言う描く手段(色えんぴつ？クレヨン？絵の具？など)の準備
            let myDraw = UIPanGestureRecognizer(target: self, action: #selector(ViewController.drawGesture(_:)))
            //let myDraw = UIPanGestureRecognizer(target: self, action: #selector(ViewController.drawGesture(sender:))
            myDraw.maximumNumberOfTouches = 1
            self.scrollView.addGestureRecognizer(myDraw)
    
        }
    
        func drawGesture(sender: AnyObject) {
    
            guard let drawGesture = sender as? UIPanGestureRecognizer else {
                print("drawGesture Error happened.")
                return
            }
    
            guard let canvas = self.canvasView.image else {
                fatalError("self.pictureView.image not found")
            }
            let touchPoint = drawGesture.location(in: canvasView)         //タッチ座標を取得
    
            switch drawGesture.state {
            case .began:
                lastPoint = touchPoint                                      //タッチ座標をlastTouchPointとして保存する
    
                //touchPointの座標はscrollView基準なのでキャンバスの大きさに合わせた座標に変換しなければいけない
                //LastPointをキャンバスサイズ基準にConvert
                let lastPointForCanvasSize = convertPointForCanvasSize(originalPoint: lastPoint!, canvasSize: canvas.size)
    
                bezierPath = UIBezierPath()
                guard let bzrPth = bezierPath else {
                    fatalError("bezierPath Error")
                }
    
                bzrPth.lineCapStyle = .round                            //描画線の設定 端を丸くする
                //bzrPth.lineWidth = defaultLineWidth                     //描画線の太さ
                bzrPth.lineWidth = lineWidth!                           //描画線の太さ
                bzrPth.move(to: lastPointForCanvasSize)
    
            case .changed:
    
[/code]

※ 修正  
//この箇所はそのままで  
① let myDraw = UIPanGestureRecognizer(target: self, action:
#selector(ViewController.drawGesture(_:)))

② @objc func drawGesture(sender: Any) --- この箇所を変えましたが

①のところで Type 'ViewController' has no member 'drawGesture'がやはり表示されます。


CC BY-SA 3.0
2018-04-14T00:34:28.343
43223
2018-04-14T06:56:03.340
2018-04-14T02:24:23.907
26811
26811
question
swift swift4
swift4 let myDraw = UIPanGestureRecognizer(target: self, action: #selector(ViewController.drawGesture(_:)))　でエラーになる


コメントに書いた「どこに書いてあるか」と言う点では正しい場所に書かれているようですが、いくつかの点で古い書き方になっているため動いていないようです。

### 1点目: メソッドの第1パラメータの引数ラベルの取り扱いがSwift3で変わった

Swift 2までは、`func myFunc(value:
Int)`のような書き方をすると、呼び出し方は`myFunc(1)`のように呼び出していました。`#selector`の中などで使うメソッド参照では`myFunc(_:)`と表現されます。

Swift 3以降では`func myFunc(value: Int)`と定義すると、呼び出しは`myFunc(value:
1)`のように引数ラベルが必要になります。またそれにともない、メソッド参照も`myFunc(value:)`になります。

これに対応するためにどちらかの修正が必要になります。

  1. メソッド参照の方を修正する
[code]     let myDraw = UIPanGestureRecognizer(target: self,

                                        action: #selector(ViewController.drawGesture(sender:)))
    
[/code]

(これは試されたのかもしれませんが、これだけではコンパイルが通りません。)

  2. メソッド参照の方は`drawGesture(_:)`のまま、メソッド定義の方を修正する。
[code]     func drawGesture(_ sender: Any) {

    
[/code]

(`AnyObject`→`Any`の変更は必須ではありませんが、最近のXcodeがデフォルトで生成するのは`Any`なので、それに合わせておきました。)

### 2点目: Swift 4では(一部例外を除き)Selectorで呼ばれるメソッドには`@objc`が必要になった

これは表題の通りです。単に`@objc`をSelector経由で呼ばれるメソッドの`func`の前に追加してください。ここでは1点目で2.の方針で修正したものとします。

[code]

    @objc func drawGesture(_ sender: Any) {
    
[/code]

* * *

ちなみに`#selector`の中で使用するメソッド参照では`クラス名.`で始まる形式の他に、`インスタンス変数名.`の形式も使えます。`target:`に`self`を指定した場合は、`self.`で始めたほうが、`self`の表すクラスにはそんなメソッドがない、なんて間違いを減らせます。

[code]

    let myDraw = UIPanGestureRecognizer(target: self,
                                        action: #selector(self.drawGesture(_:)))
    
[/code]

* * *

私が見逃したところでまだ何かあるかもしれません。1点目と2点目を正しく修正してもコンパイルエラーが出るようなら、コメント等でお知らせください。


CC BY-SA 3.0
2018-04-14T02:10:21.397
43225
2018-04-14T06:56:03.340
2018-04-14T06:56:03.340
13972
13972
43223
answer