Sending a Parameter Argument to Function Through Uitapgesturerecognizer Selector

Pass extra argument for UItapgestureRecognizer with selector

Short answer: no

The selector is called by the UITapGestureRecognizer, and you have no influence on what parameters it passes.

However, what you can do is query the recognizer's view property to get the same information.

func doubleTapComment(recognizer: UIGestureRecognizer) {
if recognizer.view == label1 {
...
}
else if recognizer.view == label2 {
...
}
}

Pass Parameter with UITapGestureRecognizer

One approach would be to subclass UITapGestureRecognizer and then set a property, I've posted an example below. You could also do some check on the sender and check if equal to some tag, class, string, e.t.c

class ViewController: UIViewController {

@IBOutlet weak var label1: UILabel!
@IBOutlet weak var image: UIImageView!

override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
image.userInteractionEnabled = true;
let tappy = MyTapGesture(target: self, action: #selector(self.tapped(_:)))
image.addGestureRecognizer(tappy)
tappy.title = "val"
}

func tapped(sender : MyTapGesture) {
print(sender.title)
label1.text = sender.title
}
}

class MyTapGesture: UITapGestureRecognizer {
var title = String()
}

There are lots of examples on SO, have a look, good luck.

How to add a parameter to UITapGestureRecognizer so that the action function can access that parameter

Make your custom View and store the parameter that you want to pass through the Gesture Recognizer inside the view.

class GestureView: UIView{

var myViewValue: String? // Or whichever type of value you want to store and send via the gesture
}

When you initiate your view, add the value as per your requirement:

    let panReceptor = GestureView()
panReceptor.myViewValue = "Hello World"

Add a simple TapGesture on this custom view and you may pass the value as below:

let tapGesture = UITapGestureRecognizer.init(target: self, action: #selector(viewTapped(sender:)))
panReceptor.addGestureRecognizer(tapGesture)


@objc func viewTapped(sender: UITapGestureRecognizer){

guard let unwrappedView = sender.view as? GestureView else { return }
print("Gesture View value : \(unwrappedView.myViewValue)")
}

In the above example I have in effect passed a String parameter through the sender.view.

You may pass any type in this manner and use the value as per your requirement in the selector method.

selector with argument gestureRecognizer

You cannot pass a parameter to a function like that. Actions - which this is, only pass the sender, which in this case is the gesture recognizer. What you want to do is get the UIView you attached the gesture to:

let gestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(labelPressed())

func labelPressed(_ recognizer:UITapGestureRecognizer){
let viewTapped = recognizer.view
}

A few more notes:

(1) You may only attach a single view to a recognizer.
(2) You might want to use both the `tag` property along with the `hitTest()` method to know which subview was hit. For example:


let view1 = UIView()
let view2 = UIView()

// add code to place things, probably using auto layout

view1.tag = 1
view2.tag = 2
mainView.addSubview(view1)
mainView.addSubview(view2)

let gestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(mainViewTapped())

func mainViewTapped(_ recognizer:UITapGestureRecognizer){

// get the CGPoint of the tap

let p = recognizer.location(in: self)
let viewTapped:UIView!

// there are many (better) ways to do this, but this works

for view in self.subviews as [UIView] {
if view.layer.hitTest(p) != nil {
viewTapped = view
}
}

// if viewTapped != nil, you have your subview

}

Passing arguments to selector in Swift

It looks like you're misunderstanding a couple of things.

When using target/action, the function signature has to have a certain form…

func doSomething()

or

func doSomething(sender: Any)

or

func doSomething(sender: Any, forEvent event: UIEvent)

where…

The sender parameter is the control object sending the action message.

In your case, the sender is the UITapGestureRecognizer

Also, #selector() should contain the func signature, and does NOT include passed parameters. So for…

func handleTap(sender: UIGestureRecognizer) {

}

you should have…

let gesture = UITapGestureRecognizer(target: self, action: #selector(handleTap(sender:)))

Assuming the func and the gesture are within a view controller, of which modelObj is a property / ivar, there's no need to pass it with the gesture recogniser, you can just refer to it in handleTap

Passing parameters to a Selector in Swift using UITapGestureRecognizer, UIImageView and UITableViewCell

You can use the view property of the UIGestureRecognizer.

Register for tap gesture:

let tap = UITapGestureRecognizer(target: self, action: "tappedMe:")
imgPost1.addGestureRecognizer(tap)
imgPost1.userInteractionEnabled = true

Now define the tappedMe method

func tappedMe(sender: UITapGestureRecognizer) {
print(sender.view?.tag)
}

PS: Don't forget to set the tag for image

How to add parameters to a generic UITapGestureRecognizer?

First of all, the selector of the target/action pattern has two fixed forms:

  • A function without parameter
  • A function with one parameter representing the sender, the object which triggered the action.

But you can add properties in a subclass and pass the parameters in the (custom) init method.

A generic in a subclass fights the framework therefore a custom dictionary (you could use just Any, too) is the better choice.

For example beside target and action the class has an userInfo dictionary and a onClick closure. The init method calls super to call the designated initializer of the tap recognizer.

class ClickListener: UITapGestureRecognizer {
var onClick : (() -> Void)?
var userInfo: [String:Any]?

init(target: Any?, action: Selector?, userInfo: [String:Any]? = nil, onClick: (() -> Void)? = nil) {
self.userInfo = userInfo
self.onClick = onClick
super.init(target: target, action: action)
}
}

And you can use it

extension UIView {

func setOnClickListener(action :@escaping () -> Void){
let tapRecogniser = ClickListener(target: self, action: #selector(onViewClicked), userInfo: ["message":"Hello World"], onClick: action)
self.addGestureRecognizer(tapRecogniser)
}

@objc func onViewClicked(_ sender: ClickListener) {
if let userInfo = sender.userInfo,
let message = userInfo["message"] as? String {
print(message)
}
sender.onClick?()
}

}

A more generic implementation is to pass the userInfo in the onClick closure.

class ClickListener: UITapGestureRecognizer {
var onClick : (([String:Any]?) -> Void)?
var userInfo: [String:Any]?

init(target: Any?, action: Selector?, userInfo: [String:Any]? = nil, onClick: (([String:Any]?) -> Void)?) {
self.userInfo = userInfo
self.onClick = onClick
super.init(target: target, action: action)
}
}

extension UIView {

func setOnClickListener(userInfo: [String:Any], action :@escaping ([String:Any]?) -> Void){
let tapRecogniser = ClickListener(target: self, action: #selector(onViewClicked), userInfo: userInfo, onClick: action)
self.addGestureRecognizer(tapRecogniser)
}

@objc func onViewClicked(_ sender: ClickListener) {
sender.onClick?(sender.userInfo)
}

}

How to pass additional parameter to UITapGestureRecognizer?

You can achieve this by creating your own TapGestureRecongnizer class which is the subclass of UITapGestureRecognizer. The example is shown below:

class MyTapGesture: UITapGestureRecognizer {
var floatValue = 0.0
}

class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let tapped = MyTapGesture.init(target: self, action: #selector(handleTap))
tapped.floatValue = 5.0
tapped.numberOfTapsRequired = 1
view.addGestureRecognizer(tapped)
}

override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}

func handleTap(recognizer: MyTapGesture) {
print(recognizer.floatValue)
}
}


Related Topics



Leave a reply



Submit