Swift: add button target in an inner class

I'm trying to set an action to call on a button touch. I created the button in IB, and in the main class I'm trying to set the needed action.

After all set up, I touch the button and nothing happens. I guess there is a problem with target or action selector: which in this case I should use? Thanks!

class View: UIView {

    private class PhoneCallSetter: UIResponder {

      private var phone: String!

      func initialize(button: UIButton!, phoneNumber: String!) {
        self.phone = phoneNumber

        button.addTarget(self, action: #selector(PhoneCallSetter.call), forControlEvents: UIControlEvents.TouchUpInside)
      }

      @objc func call() {
        if let phoneCallURL: NSURL = NSURL(string: "tel://\(phone)") {
            let application: UIApplication = UIApplication.sharedApplication()
            if (application.canOpenURL(phoneCallURL)) {
                application.openURL(phoneCallURL);
            }
        }
      }
   }

@IBOutlet weak var button: UIButton!

// somewhere down there I call
func setPhone() {
    PhoneCallSetter().initialize(button, phoneNumber: "123-456")
}}

Upvotes: 0

Views: 451

Answers (5)

user2319290
user2319290

Reputation: 7

Try to change the name of button outlet here:

@IBOutlet weak var button: UIButton!

your function

func initialize(button: UIButton!, phoneNumber: String!)

is not able to recognise the actual button pressed, as you have the button name same at both the places.

Upvotes: 0

Suresh Kansujiya
Suresh Kansujiya

Reputation: 175

your target in inner class should be nested(inherited)

button.addTarget(View. PhoneCallSetter, action: #selector(PhoneCallSetter.call), forControlEvents: UIControlEvents.TouchUpInside)

something like this.

Upvotes: 0

OOPer
OOPer

Reputation: 47876

In your setPhone() method, you create a new instance of PhoneCallSetter, and calling its method initialize(_:phoneNumber:), but you are not keeping the instance anywhere.

For an object to be an action target, the object needs to be kept somewhere with a strong reference. UIButton (or any other UIControl) just holds the target object with weak reference.

Which means, once the method initialize(_:phoneNumber:) has finished execution, the instance of PhoneCallSetter is released. An action method sent to already released instance may be ignored silently.

Thus, you need to keep the instance with strong reference, such as:

var phoneCallSetter: PhoneCallSetter?
func setPhone() {
    self.phoneCallSetter = PhoneCallSetter()
    self.phoneCallSetter!.initialize(button, phoneNumber: "123-456")
}

But I do not understand why you dare make a private class as an action target. Non-standard way forces you to make non-standard effort, which you'd better avoid.

Upvotes: 1

Duncan C
Duncan C

Reputation: 131418

It looks to me like the problem is your setPhone() function. That function creates a new instance of your PhoneCallSetter class and then calls it's initialize method, but you then never do anything with that object. You should either create a UIView object in your storyboard and change it's class to PhoneCallSetter (probably best) or add a PhoneCallSetter object to your view hierarchy in code. (But that would mean setting up constraints on it, which is a little tricky.)

Upvotes: 0

Amanpreet
Amanpreet

Reputation: 1321

For Example:

class FV_OrderComplete: UIView {
   var block_OrderSubmit: (() -> ())!
    var block_checkPincode: ((String) -> ())!

    @IBAction func didActButtonOK(_ sender: AnyObject)
        {
            if block_OrderSubmit != nil{
                block_OrderSubmit()
            }

           if block_checkPincode != nil{
            block_checkPincode(txtField_Pincode.text!)
        }
    }
}

In Controller class use the block where you want. It will only call when you press the button:

self.vew.block_OrderSubmit  =
            {
                ()in
               //write code
        }

      self.vew.block_checkPincode =
        {
            (str_Pincode: String) in
             //write code and use the passed data
        }

Note: Here vew is object of UIView class.

Upvotes: 0

Related Questions