Programming a UIButton is not working in Swift 4 Xcode 9 Beta 6, Cannot add target
Asked Answered
A

2

13

In the past I had no problem creating a UIButton programmatically, but ever since I've been using Xcode 9 and Swift 4, I cannot find a way to make this error go away.

//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)")
}

Error Message: 'NSInvalidArgumentException', reason: '-[Playing.MainMenuViewController pressButton:]: unrecognized selector sent to instance 0x10440a6b0'

Ademption answered 20/8, 2017 at 17:8 Comment(5)
Your first line of code never compiles in any versions of Swift. So, you should have had problems, or else, you have changed too much from your no-problem code. Anyway, you need to show where that line is placed. Show whole method including the line.Haley
One more, can you tell me where you get Xcode 9 Beta 6? The version of Xcode available on Apple's download page I can find now is Xcode 9 beta 5 (Build 9M202q).Haley
Thanks, you are correct. I've edited the code to a version that did work back in the days of Swift 2. Can you see what I'm talking about now?Ademption
I believe I can see. But your issue is just a combination of an issue of Swift 2.2 and another of Swift 4.Haley
Why I have to even google this stuff. WTF??Carbineer
H
22

Two points.

First, since Swift 2.2 (bundled with Xcode 7.3, released more than a year ago), recommended selector notation is #selector(...). With using the notation, you may get more useful diagnostic messages, than using other notation.

(You should not ignore any warnings displayed with recommended settings.)

Seconde, in Swift 4, you need to explicitly annotate methods invoked through selector with @objc. (In very limited cases, Swift implicitly applies the notation, but not many.)

So, your code shown should be:

//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)")
}

This is not critical, but you should better follow a simple coding rule of Swift -- only type names are capitalized.

Better rename your PositionStartButton, StartButton and ScrollView, if you think you may have another chance to show your code publicly.

Haley answered 21/8, 2017 at 11:11 Comment(2)
you mean that we now from onwards start writinf @objc before func in swift 4?Interpellate
@ArgaPK, frankly I do not understand what you mean, but we need to annotate methods with @objc when the methods are called through ObjC selectors, unless some other rule implies @objc.Haley
E
1
// Add Target   

 buttonName.addTarget(self, action: #selector(ViewController.handleButton(_:)), for: .touchUpInside)

    // Handle Action

        @objc func handleButton(_ sender: AnyObject) {


    }
Elaterin answered 18/5, 2018 at 15:34 Comment(1)
While this answer is probably correct and useful, it is preferred if you include some explanation along with it to explain how it helps to solve the problem. This becomes especially useful in the future, if there is a change (possibly unrelated) that causes it to stop working and users need to understand how it once worked.Turbary

© 2022 - 2024 — McMap. All rights reserved.