user11248377
user11248377

Reputation:

How can I pass multiple parameters to Swift #selector?

I want to pass ina second parameter to a selector function that comes from another function:

func bindToKeyboardNew(constraint: NSLayoutConstraint) { // <- this parameter 
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(_:constraint:)), name: UIResponder.keyboardWillShowNotification, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: UIResponder.keyboardWillHideNotification, object: nil)
}

@objc func keyboardWillShow(_ notification: NSNotification, constraint: NSLayoutConstraint) // <- To This selector {

}

Upvotes: 1

Views: 2084

Answers (2)

Kamil.S
Kamil.S

Reputation: 5543

As @rmaddy mentioned in the comment this cannot be done the way you're asking for.

In this part

NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(_:constraint:)), name: UIResponder.keyboardWillShowNotification, object: nil)

you have no control over how exactly the selector is sent (and with what args).

UIKit internally in its private implementation does something like this (let's ignore for a second that its implementation isn't really Swift, that's not important here):

NotificationCenter.default.post(name: NSNotification.Name(rawValue: UIResponder.keyboardWillShowNotification), object: uiwindow, userInfo: systemUserInfoForKeyboardShow)

What it means the selector is already sent and there's no way to add something extra to optional userInfo (you could do that if the .post(...) did happen in your code, but that's not the case here).

You need an alternative way to access your current NSLayoutConstraint object inside the keyboard selector show/hide handlers. Maybe it should be a property in your ViewController , maybe some state of your AppDelegate or maybe something completely different, it's impossible to tell not knowing rest of your code.

EDIT: As per your added comment I'd assume that you have something like this:

class ViewController: UIViewController {
    @IBOutlet var constraint: NSLayoutConstraint?
}

If so you can simply access the constraint in your selector handler inside the VC:

class ViewController: UIViewController {
    @IBOutlet var constraint: NSLayoutConstraint?
    @objc func keyboardWillShow(_ notification: NSNotification) {
       //do something with the constraint 
       print(constraint)
    }
}

There's also a dedicated UIKeyboardWillChangeFrameNotification perhaps it could provide you with what you need out of the box. See the answer here

Upvotes: 0

T.Nhan
T.Nhan

Reputation: 188

The easier way you can pass data is creating a custom class. Example I need pass data through UITapGestureRecognizer.

First, create a custom UITapGestureRecognizer and define a instance which is your data

class CustomTapGesture: UITapGestureRecognizer {
    var data: YourData
}
let tapGesture = CustomTapGesture(target: self, action: #selector(tapGesture(_:)))
tapGesture.data = yourData
yourView.addGestureRecognizer(tapGesture)

#selector function

@objc func tap(_ sender: UITapGestureRecognizer) {
    if let sender = sender as? CustomTapGesture {
       yourData = sender.data
       // do something with your data
    }
}

Upvotes: 3

Related Questions