web-dev-qa-db-ja.com

「#selector」の引数が「@objc」メソッド、プロパティ、または初期化子を参照していません

Objective-Cで記述されたSwift 3 UIButtonサブクラスにサブクラス化しました。

ターゲットを追加しようとすると、エラーコードで失敗します。

class ActionButton: JTImageButton {

    func action() {

    }

    func configure()) {
        // ...
        self.addTarget(self, action: #selector(self.action()), for: .touchUpInside)
        // error: 
        // Argument of '#selector' does not refer to an '@objc' method, property, or initializer

    }
}
31
MJQZ1347

あなたがしなければならないのは、@objcとしてfuncをマークすることであり、self参照や括弧は必要ありません

class ActionButton: JTImageButton {

    @objc func btnAction() {

    }

    func configure() {
        // ...
        self.addTarget(self, action: #selector(btnAction), for: .touchUpInside)
        // error: 
        // Argument of '#selector' does not refer to an '@objc' method, property, or initializer

    }
}

必要に応じてprivateにすることもできます

28
cjrieck

問題は、#selector(self.action())で、self.action()メソッド呼び出しであることです。 callメソッドは必要ありません。 nameメソッドにしたい。代わりに#selector(action)と言ってください:括弧を失い、さらにselfは必要ありません。

38
matt

@objcキーワードを完全なメソッドの前に追加すると、このエラーが発生します。最後に、私は次のように解決策を見つけました enter image description here

上記の図のように、メソッドの後ろに余分な括弧があります。私がすべきことはそれを削除することです、それはうまくいきました。

4
Victor John

別の回答のコメントから追加されました:func action()は、関数名とアクションの選択として不適切であるだけでなく、ビルドに失敗します。 (ただし、これらを設定するinit()にtarget/actionを渡すときに明確にするために、入力関数パラメーターとして使用できます。)これをMyAction()に置き換えています明確にするために。


これを試して:

self.addTarget(self, action: #selector(MyAction), for: .touchUpInside)

とは言っても、MyAction()関数をボタンのスーパービューに移動すると、はるかに優れた設計になります。これにより、基本的なMVC設計との整合性が向上します。

スーパービュー:

let myButton = ActionButton()
// include other button setup here
myButton.addTarget(self, action: #selector(MyAction), for: .touchUpInside

func action(_ sender: ActionButton) {
    // code against button tap here
}

これの代替コーディング、View Controllerで「action()」メソッドを維持しながら、ボタンに「only」「addTarget」を移動:

self.addTarget(superview?, action(superview?.MyAction), for: .touchUpInside)

「MyAction()」メソッドをスーパービューに移動することを検討するように求めているのはなぜですか?二重:

  • ボタンだけでなく、ビュー内の他のすべてのサブビューも制御し、通常はView Controllerを介して相互に作用します。
  • 他のシナリオでボタンを再利用しやすくします。
2
dfd

self.action()と言う代わりに、ActionButton.action()を使用します。

1
Bawpotter

追加の関数を追加してもかまわない場合は、関数をネストできます。

self.addTarget(self, action: myAction, for: UIControlledEvent)

myAction(){
    @obj.methodYouWantToCall(//parameters//)
}
0
Eugene Temlock