過去にはプログラムでUIButtonを作成することに問題はありませんでしたが、Xcode 9とSwift 4を使用して以来、このエラーを解消する方法は見つかりません。
//Adding target to UIButton
func PositionStartButton(xOffset: Float){
StartButton.frame = CGRect(x: Int(0 - 40 + xOffset), y: 0, width: 80, height: 80)
StartButton.setImage(#imageLiteral(resourceName: "Logo_Final_WHITE_Face"), for: .normal)
StartButton.addTarget(self, action: "pressButton:", for: .touchUpInside)
ScrollView.addSubview(StartButton)
}
//The target function
func pressButton(_ sender: UIButton){
print("\(sender)")
}
エラーメッセージ: 'NSInvalidArgumentException'、理由: '-[Playing.MainMenuViewController pressButton:]:unrecognized selector sent sent to instance 0x10440a6b0'
2つのポイント。
まず、Swift 2.2(1年以上前にリリースされたXcode 7.3にバンドルされている)以降、推奨されるセレクター表記は#selector(...)
です。表記法を使用すると、他の表記法を使用するよりも便利な診断メッセージが表示される場合があります。
(推奨設定で表示される警告を無視しないでください。)
次に、Swift 4では、セレクターを介して呼び出されたメソッドに@objc
で明示的に注釈を付ける必要があります。 (非常に限られた場合に、Swiftは暗黙的に表記法を適用しますが、多くは適用しません。)
したがって、表示されるコードは次のようになります。
//Adding target to UIButton
func PositionStartButton(xOffset: Float){
StartButton.frame = CGRect(x: Int(0 - 40 + xOffset), y: 0, width: 80, height: 80)
StartButton.setImage(#imageLiteral(resourceName: "Logo_Final_WHITE_Face"), for: .normal)
StartButton.addTarget(self, action: #selector(self.pressButton(_:)), for: .touchUpInside) //<- use `#selector(...)`
ScrollView.addSubview(StartButton)
}
//The target function
@objc func pressButton(_ sender: UIButton){ //<- needs `@objc`
print("\(sender)")
}
これは重要ではありませんが、Swiftの単純なコーディング規則に従う必要があります。タイプ名のみが大文字になります。
コードを公開する別の機会があると思われる場合は、PositionStartButton
、StartButton
、およびScrollView
の名前を変更してください。
// Add Target
buttonName.addTarget(self, action: #selector(ViewController.handleButton(_:)), for: .touchUpInside)
// Handle Action
@objc func handleButton(_ sender: AnyObject) {
}