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
Spawning a Spritekit Node at a Random Time
Convert Firdatasnapshot to Custom Type
Cannot Use Mutating Member on Immutable Value of Type
How to Get Day and Month from Date Type - Swift 4
Swift Safe Area Layout Guide and Visual Format Language
Lazy Readonly Property in Swift
Access Properties via Subscripting in Swift
Swift Difference Between Final Var and Non-Final Var | Final Let and Non-Final Let
How to Properly Implement the Equatable Protocol in a Class Hierarchy
How to Restrict the Type That a Function Throws in Swift
Result Values in '? :' Expression Have Mismatching Types 'Some View' and '...'
Uitesting Xcode 7: How to Tell If Xcuielement Is Visible
How to Remove Numbers from a String in Swift
Swift: Loop Over Array Elements and Access Previous and Next Elements