Swift3 iOS - How to make UITapGestureRecognizer trigger function - ios

I am trying to add a UITapGesture to a UIButton so it will trigger a function when tapped. I am using Swift 3 and is getting some error:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[SwiftRunner.ViewController tapBlurButton]: unrecognized selector sent to instance 0x149e07610'
This is roughly what I have:
// Swift 3
import UIKit
class ViewController {
#IBOutlet weak var qsBlurButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
let tapGesture = UITapGestureRecognizer(target: self, action: Selector(("tapBlurButton")))
qsBlurButton.addGestureRecognizer(tapGesture)
}
func tapBlurButton(sender: UITapGestureRecognizer) {
print("Please Help!")
}
}

From your code you are using swift 3.0 so change your selector syntax like this
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(self.tapBlurButton(_:)))
and Your function like this
func tapBlurButton(_ sender: UITapGestureRecognizer) {
print("Please Help!")
}
Edit:
Not idea that you are using button with tap gesture, instead of that use inbuilt method addTarget for button no need to create tap gesture for it like this
qsBlurButton.addTarget(self, action: #selector(self.tapBlurButton(_:)), forControlEvents: .TouchUpInside)
func tapBlurButton(_ sender: UIButton) {
print("Please Help!")
}

Swift 3
In the case where the func for the selector looks like this (note: it doesn't have a _):
func tapBlurButton(sender: UITapGestureRecognizer) {
print("Please Help!")
}
Then the selector looks like this:
#selector(self.tapBlurButton(sender:))
So the final code for the selector is this:
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(self.tapBlurButton(sender:)))
If you do not specify that the first parameter has _, then you need to use the full name of the first parameter.

To add a gesture recognizer you have to create one indicating which function it will call:
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(self.handleTapFrom(recognizer:)))
Then add it to the element you need. (You are using a button, and as others have explained buttons have their native 'addTarget' methods)
For explanation purposes imagine you want to add it to an UIView:
self.someView.addGestureRecognizer(tapGestureRecognizer)
And don't forget that some elements are "not user interactive" by default so you might have to change that property too:
self.someView.isUserInteractionEnabled = true
In Swift 4 the function needs the #objc declaration:
#objc func handleTapFrom(recognizer : UITapGestureRecognizer)
{
// Some code...
}

Related

figure out which button was pressed while differ between long-press and tap. swift

So I have listeners for a long and short-press on buttons, but I need to know what button was pressed.
Is it possible to find out what button was pressed in the tap and long function, or will I need to do two functions for each button?
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(tap))
let longGesture = UILongPressGestureRecognizer(target: self, action: #selector(long))
longGesture.minimumPressDuration = 0.5
smallOption.addGestureRecognizer(tapGesture)
mediumOption.addGestureRecognizer(tapGesture)
largeOption.addGestureRecognizer(tapGesture)
smallOption.addGestureRecognizer(longGesture)
mediumOption.addGestureRecognizer(longGesture)
largeOption.addGestureRecognizer(longGesture)
#objc func tap(_ sender: UIGestureRecognizer){
print("short-press")
}
#objc func long(_ sender: UIGestureRecognizer){
print("long-press")
}
The main issue, in this case, is both gestures will be added ONLY for the largeOption button! To clarify, the gesture is added only for one component, which in your case, it should be added only for the latest one (which is largeOption):
smallOption.addGestureRecognizer(tapGesture) <-- skipped
mediumOption.addGestureRecognizer(tapGesture) <-- skipped
largeOption.addGestureRecognizer(tapGesture) <-- added
smallOption.addGestureRecognizer(longGesture) <-- skipped
mediumOption.addGestureRecognizer(longGesture) <-- skipped
largeOption.addGestureRecognizer(longGesture) <-- added
Logically speaking, this might be the answer to your question:
Is it possible to find out what button was pressed in the tap and long function, or will I need to do two functions for each button?
you need to add two gestures for each button because a particular gesture can only be added to one view.
However, you don't have to declare new action methods in addition to #objc func tap(_ sender: UIGestureRecognizer) and #objc func long(_ sender: UIGestureRecognizer) existing ones. What you could do instead is to check the sender's view. Example:
Let's assume that we manually added tow gestures for each button:
// gestures:
let smallOptionTapGesture = UITapGestureRecognizer(target: self, action: #selector(tap))
let smallOptionLongGesture = UILongPressGestureRecognizer(target: self, action: #selector(long))
smallOptionLongGesture.minimumPressDuration = 0.5
let mediumOptionTapGesture = UITapGestureRecognizer(target: self, action: #selector(tap))
let mediumOptionLongGesture = UILongPressGestureRecognizer(target: self, action: #selector(long))
mediumOptionLongGesture.minimumPressDuration = 0.5
let largeOptionTapGesture = UITapGestureRecognizer(target: self, action: #selector(tap))
let largeOptionLongGesture = UILongPressGestureRecognizer(target: self, action: #selector(long))
largeOptionLongGesture.minimumPressDuration = 0.5
// adding them:
smallOption.addGestureRecognizer(smallOptionTapGesture)
mediumOption.addGestureRecognizer(mediumOptionTapGesture)
largeOption.addGestureRecognizer(largeOptionTapGesture)
smallOption.addGestureRecognizer(smallOptionLongGesture)
mediumOption.addGestureRecognizer(mediumOptionLongGesture)
largeOption.addGestureRecognizer(largeOptionLongGesture)
Therefore, what you could do is:
#objc func tap(_ sender: UIGestureRecognizer) {
// an example of how you could check the button
if sender.view == smallOption {
print("small short-press")
} else if sender.view == mediumOption {
print("medium short-press")
} else if sender.view == largeOption {
print("large short-press")
}
}
#objc func long(_ sender: UIGestureRecognizer) {
// you could apply the same above approach here
}
The other option is to create action methods for each button separately.
You do not need two functions for the same gesture for each button. Change the method definition to accept UIButton (in your case) instead of UIGestureRecognizer. Afterwards, check the sender by verifying the tag or the type directly...
#objc func tap(_ sender: UIButton){
switch sender {
case button1: // or by tags of buttons
case button2:
...
default: break
}

UILabel set onClick

I'm building an application in Swift 3, so I want to call a function if I click on a particular UILabel, so I'm write this code but not works:
let tap = UITapGestureRecognizer(target: self, action: #selector(ViewController.tapFunction))
self.labelTemp.isUserInteractionEnabled = true
self.labelTemp.addGestureRecognizer(tap)
How can I render UILabel clickable ?
Set user interaction enabled for the UILabel and add the below code in the viewDidLoad()
self.label.isUserInteractionEnabled = true
let tap = UITapGestureRecognizer(target: self, action: #selector(self.labelTapped))
self.label.addGestureRecognizer(tap)
Add the tap action function as below :
#objc func labelTapped(_ gestureRecognizer: UITapGestureRecognizer) {
print("Label clicked")
}
Please make user that there is no other transparent view overlapping the UILabel in the view. If the UILabel is a part of another view then please make sure that the container View's user interaction is enabled.
Hope this helps.
Your selector should be an #objc func within self.
<#YourLabel#>.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.handleLabelTap)))
And when the user taps the label it will trigger:
#objc func handleLabelTap() {
// handle label tap here
}
You are lacking a function to trigger when the gesture touch is recognized. You need to add following:
let tap = UITapGestureRecognizer(target: self, action: #selector(tapFunction(_:)))
self.labelTemp.isUserInteractionEnabled = true
self.labelTemp.addGestureRecognizer(tap)
#objc func tapFunction(_ gestureRecognizer: UITapGestureRecognizer) {
// handle label tap here
}
Please ensure that You have connected the outlet to UILabel because I have created simple demo code by copy-paste your code and it is worked as expected.
override func viewDidLoad() {
super.viewDidLoad()
let tap = UITapGestureRecognizer(target: self, action: #selector(tapFunction))
self.labelTemp.isUserInteractionEnabled = true
self.labelTemp.addGestureRecognizer(tap)
}
#objc func tapFunction() {
print("tapFunction")
}
I suggest, Please remove UILabel from UIViewController and add it again.
Download sample code
Note: - Please ensure that user-interaction of UILabelis enabled
First you need to add Tap Gesture into storyboard
Create Action of that particular gesture
override func viewDidLoad() {
super.viewDidLoad()
let tapOnLabel = UITapGestureRecognizer(target: self, action: #selector(self.tapGestireAction))
self.labelTemp.isUserInteractionEnabled = true
self.labelTemp.addGestureRecognizer(tapOnLabel)
}
#IBAction func tapGestureAction(_ sender: UITapGestureRecognizer) {
//Perform action
}

Swift TapGestureRecognizer and UIButton [duplicate]

This question already has an answer here:
Swift: "Unrecognized selector sent to instance" error when trying to use tap gesture
(1 answer)
Closed 4 years ago.
I'm new to Swift so i'm sorry for any type of mistakes.
In my View Controller i have a view, CanvasView, and i want the user clicks on a button and add a shape where taps. I create a uiview named ShapeSquare and I have three buttons with three different shapes. Unfortunately i don't understand where i'm wrong. This is only a part of the code.
Any suggestions will be appreciated!
#IBOutlet weak var CanvasView: CanvasView!
override func viewDidLoad() {
super.viewDidLoad()
let tapGR = UITapGestureRecognizer(target: self, action: Selector(("didTap")))
tapGR.numberOfTapsRequired = 1
CanvasView.isUserInteractionEnabled = true
CanvasView.addGestureRecognizer(tapGR)
}
func didTap(tapGR: UITapGestureRecognizer) {
let tapPoint = tapGR.location(in: CanvasView)
let shapeView = ShapeSquare(origin: tapPoint)
CanvasView.addSubview(shapeView)
}
#IBAction func SquareShape(_ sender: UIButton) {
CanvasView.setNeedsDisplay()
}
1-
let tapGR = UITapGestureRecognizer(target: self, action: #selector(didTap(_:)))
2-
#objc func didTap(_ tapGR: UITapGestureRecognizer) {

unrecognized selector sent to instance Error when trying to setTarget action [duplicate]

I've searched for solutions to this problem but couldn't find anything that seems to address it in my case. I'm getting the above exception from a UITapGestureRecognizer.
Here's the simplified code:
import UIKit;
class ViewController : UIViewController, UIScrollViewDelegate
{
#IBOutlet weak var scrollView:UIScrollView!;
var imageView:UIImageView!;
override func viewDidLoad()
{
super.viewDidLoad();
... set up imageView/scrollView here ...
let doubleTapRecognizer = UITapGestureRecognizer(target: self, action: "onScrollViewDoubleTapped");
doubleTapRecognizer.numberOfTapsRequired = 2;
doubleTapRecognizer.numberOfTouchesRequired = 1;
scrollView.addGestureRecognizer(doubleTapRecognizer);
}
func onScrollViewDoubleTapped(recognizer:UITapGestureRecognizer)
{
}
}
Can anyone tell what is wrong with this code? It seems all correct to me. I suspect that it has to do with assigning ViewController as delegate to scrollView (or vice versa)? However the ViewController is set as the delegate to scrollView. But maybe it's something else that causes this error?
Try adding a colon to your selector string.
let doubleTapRecognizer = UITapGestureRecognizer(target: self, action: "onScrollViewDoubleTapped:");
As cabellicar123 mentioned, this indicates that the selector takes an argument.
Swift 4 using #selector.
let tapGesture: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(didSelectItem(sender:)))
#objc func didSelectItem(sender: AnyObject?) {
print("didSelectItem: \(sender)")
}
Also try adding a parameter to your method:
...(target: self, action: "yourMethodName:")
func yourMethodName(sender: AnyObject?)
{
println("Clicked yourMethodName")
}
Maybe could help someone: I had this error because I declared private the selector method:
func setup() {
let singleFingerTap = UITapGestureRecognizer(target: self, action: "didTapOnViewInteraction:")
singleFingerTap.numberOfTapsRequired = 1
self.viewInteraction.addGestureRecognizer(singleFingerTap)
}
private func didTapOnViewInteraction(recognizer: UITapGestureRecognizer) {
}
Removing "private" keyword, all works great!
for swift 4
override func viewDidLoad() {
super.viewDidLoad()
let tap = UITapGestureRecognizer(target: self, action: #selector(SignUpViewController.click))
userImage.addGestureRecognizer(tap)
userImage.isUserInteractionEnabled = true
}
#objc func click()
{
print("Tapped on Image")
}
where SignUpViewController is your viewcontroller name
In my case, with Swift 4, the selector was correctly defined, but since the item with the gesture was inside a collection view, it was causing the selector not to be found. I implemented a custom cell and configured the selector inside of it
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "recent", for: indexPath) as! MyCollectionViewCell
cell.configureGestureWith(entry: recentEntries.sorted(by: {$0.createdAt > $1.createdAt})[indexPath.row], sender: self)
Hope this helps some one.

Swift 2.2 - Value of type ViewController has no member action

I have been getting the error "Value of type 'ViewController' has no member 'action'"
(action being the function)
Here is the code I am using for the function and Gesture Recogniser
let uilpgr = UILongPressGestureRecognizer(target: self, action: #selector(self.action))
uilpgr.minimumPressDuration = 2
Map.addGestureRecognizer(uilpgr)
func action(gestureRecogniser: UIGestureRecognizer) {
print("Gesture Recognised")
}
let uilpgr = UILongPressGestureRecognizer(target: self, action: #selector(self.action))
This is where the error occurs at self.action
What am I doing wrong and how do I fix it?
the accepted Blake Lockley's answer was right before Swift 4; however in Swift 4, the code need to be changed to the following in order to be compiled correctly (add the #objc marker to the target function):
override func viewDidLoad() {
super.viewDidLoad()
let uilpgr = UILongPressGestureRecognizer(target: self, action: #selector(ViewController.action))
}
#objc func action(gesture:UIGestureRecognizer){
print("receives gesture")
}
Your method action is declared locally within the same method that is creating the gesture recognizer.
To resolve this move your action method outside of the method it is currently in. So that is is its own method of the class ViewController and not inside any other functions.
This is working on Xcode 8:
override func viewDidLoad() {
super.viewDidLoad()
let uilpgr = UILongPressGestureRecognizer(target: self, action: #selector(ViewController.action))
}
func action(gesture:UIGestureRecognizer){
print("receives gesture")
}

Resources