[ios] How to use addTarget method in swift 3

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

This question is related to ios swift selector

The answer is


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.


  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) {

    }

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

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.


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)

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(){
    //...
}

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

Try this

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

Just add parenthesis with name of method.

Also you can refer link : Value of type 'CustomButton' has no member 'touchDown'


Instead of

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

Try:

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

That should fix the compile error!!!


Try this with Swift 3

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

Good luck!


Examples related to ios

Adding a UISegmentedControl to UITableView Crop image to specified size and picture location Undefined Symbols error when integrating Apptentive iOS SDK via Cocoapods Keep placeholder text in UITextField on input in IOS Accessing AppDelegate from framework? Autoresize View When SubViews are Added Warp \ bend effect on a UIView? Speech input for visually impaired users without the need to tap the screen make UITableViewCell selectable only while editing Xcode 12, building for iOS Simulator, but linking in object file built for iOS, for architecture arm64

Examples related to swift

Make a VStack fill the width of the screen in SwiftUI Xcode 10.2.1 Command PhaseScriptExecution failed with a nonzero exit code Command CompileSwift failed with a nonzero exit code in Xcode 10 Convert Json string to Json object in Swift 4 iOS Swift - Get the Current Local Time and Date Timestamp Xcode 9 Swift Language Version (SWIFT_VERSION) How do I use Safe Area Layout programmatically? How can I use String substring in Swift 4? 'substring(to:)' is deprecated: Please use String slicing subscript with a 'partial range from' operator Safe Area of Xcode 9 The use of Swift 3 @objc inference in Swift 4 mode is deprecated?

Examples related to selector

How to use addTarget method in swift 3 What is the Swift equivalent of respondsToSelector? @selector() in Swift? Trying to handle "back" navigation button action in iOS jQuery select child element by class with unknown path android button selector How do I select a sibling element using jQuery? Passing parameters on button action:@selector "unrecognized selector sent to instance" error in Objective-C Objective-C: Calling selectors with multiple arguments