How to use addTarget method in swift 3

IosSwiftSelector

Ios Problem Overview


here is my button object

    let loginRegisterButton:UIButton = {
    let button = UIButton(type: .system)
    button.backgroundColor = UIColor(r: 50 , g: 80, b: 130)
    button.setTitle("Register", for: .normal)
    button.translatesAutoresizingMaskIntoConstraints = false
    button.setTitleColor(.white, for: .normal)
    button.addTarget(self, action:#selector(handleRegister), for: .touchUpInside)
    return button
}()

and here is my function

    func handleRegister(){
  
    FIRAuth.auth()?.createUser(withEmail: email, password: password,completion: { (user, error) in
        
        if error != nil
        { print("Error Occured")}
            
        else
        {print("Successfully Authenticated")}
    })        
}

I'm getting compile error, if addTarget removed it compiles successfully

Ios Solutions


Solution 1 - Ios

Yes, don't add "()" if there is no param

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

and if you want to get the sender

button.addTarget(self, action:#selector(handleRegister(_:)), for: .touchUpInside). 

func handleRegister(sender: UIButton){
   //...
}

Edit:

button.addTarget(self, action:#selector(handleRegister(_:)), for: .touchUpInside)

no longer works, you need to replace _ in the selector with a variable name you used in the function header, in this case it would be sender, so the working code becomes:

button.addTarget(self, action:#selector(handleRegister(sender:)), for: .touchUpInside)

Solution 2 - Ios

Try this with Swift 4

buttonSection.addTarget(self, action: #selector(actionWithParam(_:)), for: .touchUpInside)
@objc func actionWithParam(sender: UIButton){
	//...
}

buttonSection.addTarget(self, action: #selector(actionWithoutParam), for: .touchUpInside)
@objc func actionWithoutParam(){
	//...
}

Solution 3 - Ios

Try this

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

Just add parenthesis with name of method.

Also you can refer link : https://stackoverflow.com/questions/39509556/value-of-type-custombutton-has-no-member-touchdown/39509985#39509985

Solution 4 - Ios

  let button: UIButton = UIButton()
    button.setImage(UIImage(named:"imagename"), for: .normal)
    button.addTarget(self, action:#selector(YourClassName.backAction(_sender:)), for: .touchUpInside)
    
    button.frame = CGRect.init(x: 5, y: 100, width: 45, height: 45)
    view.addSubview(button)
    
    @objc public func backAction(_sender: UIButton) {
        
    }

Solution 5 - Ios

Try with swift 3

cell.TaxToolTips.tag = indexPath.row
        cell.TaxToolTips.addTarget(self, action: #selector(InheritanceTaxViewController.displayToolTipDetails(_:)), for:.touchUpInside)


 @objc func displayToolTipDetails(_ sender : UIButton) {
        print(sender.tag)
        let tooltipString = TaxToolTipsArray[sender.tag]
        self.displayMyAlertMessage(userMessage: tooltipString, status: 202)    
}

Solution 6 - Ios

In swift 3 use this -

object?.addTarget(objectWhichHasMethod, action: #selector(classWhichHasMethod.yourMethod), for: someUIControlEvents)

For example(from my code) -

self.datePicker?.addTarget(self, action:#selector(InfoTableViewCell.datePickerValueChanged), for: .valueChanged)

Just give a : after method name if you want the sender as parameter.

Solution 7 - Ios

Try this with Swift 3

button.addTarget(self, action:#selector(ClassName.handleRegister(sender:)), for: .touchUpInside)

Good luck!

Solution 8 - Ios

The poster's second comment from September 21st is spot on. For those who may be coming to this thread later with the same problem as the poster, here is a brief explanation. The other answers are good to keep in mind, but do not address the common issue encountered by this code.

In Swift, declarations made with the let keyword are constants. Of course if you were going to add items to an array, the array can't be declared as a constant, but a segmented control should be fine, right?! Not if you reference the completed segmented control in its declaration.

Referencing the object (in this case a UISegmentedControl, but this also happens with UIButton) in its declaration when you say .addTarget and let the target be self, things crash. Why? Because self is in the midst of being defined. But we do want to define behaviour as part of the object... Declare it lazily as a variable with var. The lazy fools the compiler into thinking that self is well defined - it silences your compiler from caring at the time of declaration. Lazily declared variables don't get set until they are first called. So in this situation, lazy lets you use the notion of self without issue while you set up the object, and then when your object gets a .touchUpInside or .valueChanged or whatever your 3rd argument is in your .addTarget(), THEN it calls on the notion of self, which at that point is fully established and totally prepared to be a valid target. So it lets you be lazy in declaring your variable. In cases like these, I think they could give us a keyword like necessary, but it is generally seen as a lazy, sloppy practice and you don't want to use it all over your code, though it may have its place in this sort of situation. What it

There is no lazy let in Swift (no lazy for constants).

Here is the Apple documentation on lazy.

Here is the Apple on variables and constants. There is a little more in their Language Reference under Declarations.

Solution 9 - Ios

Instead of

let loginRegisterButton:UIButton = {
//...  }()

Try:

lazy var loginRegisterButton:UIButton = {
//...  }()

That should fix the compile error!!!

Solution 10 - Ios

the Demo from Apple document. https://developer.apple.com/documentation/swift/using_objective-c_runtime_features_in_swift

import UIKit
class MyViewController: UIViewController {
    let myButton = UIButton(frame: CGRect(x: 0, y: 0, width: 100, height: 50))
    
    override init(nibName nibNameOrNil: NSNib.Name?, bundle nibBundleOrNil: Bundle?) {
        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
        // without parameter style
        let action = #selector(MyViewController.tappedButton)
        // with parameter style
        // #selector(MyViewController.tappedButton(_:))
        myButton.addTarget(self, action: action, forControlEvents: .touchUpInside)
    }
    
    @objc func tappedButton(_ sender: UIButton?) {
        print("tapped button")
    }
    
    required init?(coder: NSCoder) {
        super.init(coder: coder)
    }
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionNinja13View Question on Stackoverflow
Solution 1 - IosDamien RomitoView Answer on Stackoverflow
Solution 2 - IosSoumenView Answer on Stackoverflow
Solution 3 - IosVRAwesomeView Answer on Stackoverflow
Solution 4 - IosGiangView Answer on Stackoverflow
Solution 5 - Ioseranda.delView Answer on Stackoverflow
Solution 6 - IosNikhil ManapureView Answer on Stackoverflow
Solution 7 - IosS EView Answer on Stackoverflow
Solution 8 - IoshlpView Answer on Stackoverflow
Solution 9 - IosEdward PizzurroView Answer on Stackoverflow
Solution 10 - IosZgpeaceView Answer on Stackoverflow