Pass Parameter with UITapGestureRecognizer - ios

Is there any way i can pass parameters with UITapGestureRecognizer?
I've seen this answered for objective-c but couldn't find an answer for swift
test.userInteractionEnabled = true
let tapRecognizer = UITapGestureRecognizer(target: self, action: Selector("imageTapped4:"))
// Something like text.myParamater
test.addGestureRecognizer(tapRecognizer)
And then receive myParameter under func imageTapped4(){}

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.

For Swift 4
In Viewdidload
let label = UILabel(frame: CGRect(x: 0, y: h, width: Int(self.phoneNumberView.bounds.width), height: 30))
label.textColor = primaryColor
label.numberOfLines = 0
label.font = title3Font
label.lineBreakMode = .byWordWrapping
label.attributedText = fullString
let phoneCall = MyTapGesture(target: self, action: #selector(self.openCall))
phoneCall.phoneNumber = "\(res)"
label.isUserInteractionEnabled = true
label.addGestureRecognizer(phoneCall)
Function as
#objc func openCall(sender : MyTapGesture) {
let number = sender.phoneNumber
print(number)
}
Write Class as
class MyTapGesture: UITapGestureRecognizer {
var phoneNumber = String()
}
Follow Step Properly and make change according to your variable , button ,label . It WORKS PROPERLY

Without subclassing, you can also add the parameter in the view layer (where the gesture is attached):
let tappy = UITapGestureRecognizer(target: self, action: #selector(self.tapped(_:)))
image.addGestureRecognizer(tappy)
image.layer.setValue(title, forKey: "anyKeyName")
Later in the handler
#objc private func tapped(_ sender: UIGestureRecognizer) {
guard let title = sender.view?.layer.value(forKey: "anyKeyName") as? String else { return }
// Do something with the title
}

The best way is to determind the parameter when the func imageTapped64is fired. You can get you params via the view (take a look to #Developer Sheldon answer)
or in many other ways.

Related

i'm trying to use image slide show cocoapods ,page indicator not work right only on my project but it works fine in demo and new projects

i'm trying to use imageSlideShow cocoapods i install it and try the demo and work fine , also used it in test project and works fine , but when i used it in my project page indicator not work and i try every thing but also not working and i create a new view controller in my project and make it init and run also not work
this is my code
import UIKit
import ImageSlideshow
class test: UIViewController {
open override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
return .portrait
}
#IBOutlet var slideshow: ImageSlideshow!
let localSource = [ImageSource(imageString: "imageLoading")!,ImageSource(imageString: "imageLoading")!,ImageSource(imageString: "logo")!]
override func viewDidLoad() {
super.viewDidLoad()
slideshow.slideshowInterval = 5.0
slideshow.pageIndicatorPosition = .init(horizontal: .center, vertical: .customUnder(padding: 50))
slideshow.contentScaleMode = UIViewContentMode.scaleAspectFill
let pageControl = UIPageControl()
pageControl.currentPageIndicatorTintColor = UIColor.lightGray
pageControl.pageIndicatorTintColor = UIColor.black
slideshow.pageIndicator = pageControl
// optional way to show activity indicator during image load (skipping the line will show no activity indicator)
slideshow.activityIndicator = DefaultActivityIndicator()
slideshow.currentPageChanged = { page in
print("current page:", page)
}
// can be used with other sample sources as `afNetworkingSource`, `alamofireSource` or `sdWebImageSource` or `kingfisherSource`
slideshow.setImageInputs(localSource)
let recognizer = UITapGestureRecognizer(target: self, action: #selector(test.didTap))
slideshow.addGestureRecognizer(recognizer)
}
// guard let im = imageUrlString else {return "hello "}
let recognizer = UITapGestureRecognizer(target: self, action: #selector(test.didTap))
slideshow.addGestureRecognizer(recognizer)*/
}
#objc func didTap() {
let fullScreenController = slideshow.presentFullScreenController(from: self)
// set the activity indicator for full screen controller (skipping the line will show no activity indicator)
fullScreenController.slideshow.activityIndicator = DefaultActivityIndicator(style: .white, color: nil)
}
}
and the result of that code make slide show but indicator not work it appear but not stretched and swapping correctly and as i marked in picture just color change and image but not clear number of image or any thing
https://drive.google.com/file/d/1z2pQ0HFUQC0F0oyajo9gRHOLcqsU4_sJ/view?usp=sharing
Looks like UIPageControl frame not set. If you remove all about pageControl - it will automatically place controls. Or you can create your own in storyboard:
#IBOutlet weak var imageSlideshow: ImageSlideshow!
#IBOutlet weak var slideshowPageControl: UIPageControl!
var slideshowInputs: [InputSource] {
let place = categoryPlaces[selectedIndex]
return [
... your inputs
]
}
func setupData(){
imageSlideshow.setImageInputs(slideshowInputs)
slideshowPageControl.numberOfPages = slideshowInputs.count
imageSlideshow.currentPageChanged = { page in
self.slideshowPageControl.currentPage = page
}
}
photoList is yours photos Model list,
import ImageSlideshow
.....
#IBOutlet weak var slideshowPageControl: UIPageControl!
#IBOutlet weak var slideShow: ImageSlideshow!
.....
func initslideShow()
{
var photos = [KingfisherSource]()
for item photoList {
photos.append(KingfisherSource(urlString: item.photoUrl)!)
}
slideShow.setImageInputs(photos)
let pageIndicator = UIPageControl()
pageIndicator.currentPageIndicatorTintColor = StyleManager.colors.colorPrimary
pageIndicator.pageIndicatorTintColor = StyleManager.colors.lightGray
slideShow.pageIndicator = pageIndicator
slideShow.activityIndicator = DefaultActivityIndicator(style: .white, color: nil)
let gestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(didTap))
slideShow.addGestureRecognizer(gestureRecognizer)
slideShow.zoomEnabled = true
slideShow.contentScaleMode = .scaleAspectFill
slideShow.pageIndicatorPosition = PageIndicatorPosition(horizontal: .left(padding: 20), vertical: .bottom)
slideshowPageControl.numberOfPages = photoList.count
slideShow.currentPageChanged = { page in
self.slideshowPageControl.currentPage = page
}
}
#objc func didTap() {
slideShow.presentFullScreenController(from: self)
}

UIImageView UITapGestureRecognizer not working

Tap gesture event not gettint called. I may be doing something wrong, but please have a look (I tried adding recognizer to self.view but still no luck) :
LoginViewController
class LoginViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let container = UIView()
container.heightAnchor.constraintEqualToConstant(50).active = true
let myVC1 = MyViewController()
let myVC2 = MyViewController()
let myVC3 = MyViewController()
let myVC4 = MyViewController()
let myStackView = UIStackView(arrangedSubviews: [myVC1.view, myVC2.view, myVC3.view, myVC4.view])
myStackView.spacing = 10
myStackView.alignment = .Fill
myStackView.distribution = .EqualSpacing
container.addSubview(myStackView)
view.addSubview(container)
}
}
MyViewController
class MyViewController: UIViewController, UIGestureRecognizerDelegate {
let ImageView = UIImageView()
override func viewDidLoad() {
super.viewDidLoad()
ImageView.backgroundColor = UIColor.blueColor()
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(pressedSocialMediaItem(_:)))
tapGestureRecognizer.delegate = self
tapGestureRecognizer.numberOfTapsRequired = 1
ImageView.userInteractionEnabled = true
ImageView.addGestureRecognizer(tapGestureRecognizer)
view.addSubview(ImageView)
}
func pressedSocialMediaItem(sender : UITapGestureRecognizer) {
print("PRESSED ! ")
}
}
I suggest using MyViewController.pressedSocialMediaItem, so your code should work like this.
class MyViewController: UIViewController, UIGestureRecognizerDelegate {
let ImageView = UIImageView()
override func viewDidLoad() {
super.viewDidLoad()
ImageView.backgroundColor = UIColor.blueColor()
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(MyViewController.pressedSocialMediaItem(_:)))
tapGestureRecognizer.delegate = self
tapGestureRecognizer.numberOfTapsRequired = 1
ImageView.userInteractionEnabled = true
ImageView.addGestureRecognizer(tapGestureRecognizer)
view.addSubview(ImageView)
}
func pressedSocialMediaItem(sender : UITapGestureRecognizer) {
print("PRESSED ! ")
}
}
I have tested the following on my machine and it works:
import UIKit
class ViewController: UIViewController, UIGestureRecognizerDelegate {
#IBOutlet weak var imageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
imageView.backgroundColor = UIColor.blueColor()
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(ViewController.pressedSocialMediaItem(_:)))
tapGestureRecognizer.delegate = self
tapGestureRecognizer.numberOfTapsRequired = 1
imageView.userInteractionEnabled = true
imageView.addGestureRecognizer(tapGestureRecognizer)
view.addSubview(imageView)
}
func pressedSocialMediaItem(sender : UITapGestureRecognizer) {
print("PRESSED ! ")
}
}
Okey, so I got it working somehow. All I need to do was to add view controllers inside my LoginViewController like so:
self.addChildViewController(myVC1)
Instead of using view.addSubview(container)
Notice: I'm not sure it is the correct way of doing this, and please comment if it's not. Meanwhile it solves my problem.

Pass extra argument for UItapgestureRecognizer with selector

I have two labels, Label1 and Label2. I want to make a single function that prints out which label is tapped by creating UITTapRecognizer for both labels calling the same function with selector that passes an argument. Below is the long way of doing it which is messy but works. If I know how to pass an argument (Int) into the selector, it would be alot cleaner.
let topCommentLbl1Tap = UITapGestureRecognizer(target: self, action: #selector(DiscoverCell().doubleTapTopComment1))
topCommentLbl1Tap.numberOfTapsRequired = 2
topCommentLbl1.userInteractionEnabled = true
topCommentLbl1.addGestureRecognizer(topCommentLbl1Tap)
let topCommentLbl2Tap = UITapGestureRecognizer(target: self, action: #selector(DiscoverCell().doubleTapTopComment2))
topCommentLbl2Tap.numberOfTapsRequired = 2
topCommentLbl2.userInteractionEnabled = true
topCommentLbl2.addGestureRecognizer(topCommentLbl2Tap)
func doubleTapTopComment1() {
print("Double Tapped Top Comment 1")
}
func doubleTapTopComment2() {
print("Double Tapped Top Comment 2")
}
Is there a way to modify the selector method such that I can do something like
func doubleTapTopComment(label:Int) {
if label == 1 {
print("label \(label) double tapped")
}
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 {
...
}
}
Provide both gesture recognizers with the same selector that takes a single parameter. That action method will be passed instance of a UIGestureRecognizer, and happily, that gesture recognizer has a property called view, which is the view to which the gr is attached.
... action: #selector(doubleTapTopComment(_:))
func doubleTapTopComment(gestureRecognizer: gr) {
// gr.view is the label, so you can say gr.view.text, for example
}
I believe a UITapGestureRecognizer can only be used for a single view. That said, you can have 2 different UITapGestureRecognizers call the same selector and then access the UITapGestureRecognizer in the function. See the following code:
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let label1 = UILabel()
label1.backgroundColor = UIColor.blueColor()
label1.frame = CGRectMake(20, 20, 100, 100)
label1.tag = 1
label1.userInteractionEnabled = true
self.view.addSubview(label1)
let label2 = UILabel()
label2.backgroundColor = UIColor.orangeColor()
label2.frame = CGRectMake(200, 20, 100, 100)
label2.tag = 2
label2.userInteractionEnabled = true
self.view.addSubview(label2)
let labelOneTap = UITapGestureRecognizer(target: self, action: #selector(ViewController.whichLabelWasTapped(_:)))
let labelTwoTap = UITapGestureRecognizer(target: self, action: #selector(ViewController.whichLabelWasTapped(_:)))
label1.addGestureRecognizer(labelOneTap)
label2.addGestureRecognizer(labelTwoTap)
}
Both UITapGestureRecognizers call the same function:
func whichLabelWasTapped(sender : UITapGestureRecognizer) {
//print the tag of the clicked view
print (sender.view!.tag)
}
If you try to add one of the UITapGestureRecognizers to both labels, then only the last one added will actually call the function.
You can do like this,
let topCommentLbl1Tap = UITapGestureRecognizer(target: self, action: #selector(labelTapped(_:)))
let topCommentLbl2Tap = UITapGestureRecognizer(target: self, action: #selector(labelTapped(_:)))
label1.addGestureRecognizer(topCommentLbl1Tap)
label2.addGestureRecognizer(topCommentLbl2Tap)
#objc
func textViewTapped(_ sender: UITapGestureRecognizer) {
if(sender.view.tag == label1.tag) {
print("I am label1")
} else if(sender.view.tag == label2.tag) {
print("I am label2")
}
}
don't forgot to set tags to labels.

iOS Swift, cannot get pinch gesture to work

i have a test project that takes text from a file, adds it to a textview and displays it.
i want to add some gestures but cannot seem to make it work...
here is the relevant code:
class ViewController2: UIViewController, UIGestureRecognizerDelegate {
#IBOutlet var textview1: UITextView!
var pinchGesture = UIPinchGestureRecognizer()
override func viewDidLoad() {
super.viewDidLoad()
self.textview1.userInteractionEnabled = true
self.textview1.multipleTouchEnabled = true
self.pinchGesture.delegate = self
self.pinchGesture = UIPinchGestureRecognizer(target: self, action: #selector(ViewController2.pinchRecognized(_:)))
self.view.addGestureRecognizer(self.pinchGesture)
}
#IBAction func pinchRecognized(pinch: UIPinchGestureRecognizer) {
self.textview1.addGestureRecognizer(pinchGesture)
self.textview1.transform = CGAffineTransformScale(self.textview1.transform, pinch.scale, pinch.scale)
pinch.scale = 1.0
}
any ideas? followed several tutorials but none seem to help. code is tested on actual iPhone...
thanks a lot
Edit for Solution:
#IBAction func pinchRecognized(pinch: UIPinchGestureRecognizer) {
var pinchScale = pinchGesture.scale
pinchScale = round(pinchScale * 1000) / 1000.0
if (pinchScale < 1) {
self.textview1.font = UIFont(name: self.textview1.font!.fontName, size: self.textview1.font!.pointSize - pinchScale)
pinchScale = pinchGesture.scale
} else {
self.textview1.font = UIFont(name: self.textview1.font!.fontName, size: self.textview1.font!.pointSize + pinchScale)
pinchScale = pinchGesture.scale
}
}
thanks to nishith Singh
Try adding the gesture recogniser to your textview in viewDidLoad instead of adding it in pinchRecognized. Currently you are adding the pinchGesture to your view which is behind your text view and hence will not receive the touch
var pinchGesture = UIPinchGestureRecognizer()
Use this code:
override func viewDidLoad() {
super.viewDidLoad()
self.textview1.userInteractionEnabled = true
self.textview1.multipleTouchEnabled = true
self.pinchGesture = UIPinchGestureRecognizer(target: self, action:#selector(pinchRecognized(_:)))
self.textview1.addGestureRecognizer(self.pinchGesture)
// Do any additional setup after loading the view.
}
#IBAction func pinchRecognized(_ pinch: UIPinchGestureRecognizer) {
let fontSize = self.textview1.font!.pointSize*(pinch.scale)/2
if fontSize > 12 && fontSize < 32{
textview1.font = UIFont(name: self.textview1.font!.fontName, size:fontSize)
}
}
You might have to hit and trial with the minimum and maximum font sizes as you want, right now the minimum font size is 12 and the maximum font size is 32.
let pinchGesture = UIPinchGestureRecognizer(target: self, action:#selector(self.pinchGesture))
func pinchGesture(sender: UIPinchGestureRecognizer){
sender.view?.transform = (sender.view?.transform)!.scaledBy(x: sender.scale, y: sender.scale)
sender.scale = 1
print("pinch gesture")
}
class ViewController2: UIViewController, UIGestureRecognizerDelegate {
#IBOutlet var textview1: UITextView!
var pinchGesture = UIPinchGestureRecognizer()
override func viewDidLoad() {
super.viewDidLoad()
self.textview1.userInteractionEnabled = true
self.textview1.multipleTouchEnabled = true
self.pinchGesture.delegate = self
self.pinchGesture = UIPinchGestureRecognizer(target: self, action: "pinchRecognized:")
self.view.addGestureRecognizer(self.pinchGesture)
}
func pinchRecognized(pinch: UIPinchGestureRecognizer) {
self.textview1.addGestureRecognizer(pinchGesture)
self.textview1.transform = CGAffineTransformScale(self.textview1.transform, pinch.scale, pinch.scale)
pinch.scale = 1.0
}
Your code is actually working. But not the way you want probably.
Initially you assigned the gesture recogniser to the view of view controller.
But then inside the method you added same gesture recogniser to the UITextView.
So it should be working on UITextView. And the gesture recogniser is removed from the view controller's view. Gesture recogniser can only have one target. Pick view controller's view or textview.
You set the delegate of self.pinchGesture before initialising.
Initialise the self.pinchGesture first.
Set the delegate.
Add self.pinchGesture to self.view
self.pinchGesture.delegate = self
self.pinchGesture = UIPinchGestureRecognizer(target: self, action:#selector(ViewController2.pinchRecognized(_:)))
self.view.addGestureRecognizer(self.pinchGesture)

Swift: UITapGestureRecognizer for uiimageview terminate app in custome view

I have some Class extended from base class (MSC_CLItem) like this:
class MSC_CLItem
{
var Type:MSC_CustomListType!
func RenderUI(Point:CGPoint) -> UIView
{
return UIView(frame: CGRect.zero)
}
}
Each extended class must to override RenderUI func to generate itself. All of the extended objects will be added in UIScrollView. Now my problem is:
An uiimageview with TapGesture inside of custom view not detect action. For example my class is:
class MSC_CLItem_Tizer : MSC_CLItem
{
var Title:String!
var Video:MSC_CLItem_TizerVideo!
var Detail:MSC_CLItem_TizerDetail!
private init(title:String!)
{
super.init()
self.Title = title
super.Type = .Tizer
}
override func RenderUI(Point:CGPoint) -> UIView
{
let v = UIImageView()
v.backgroundColor = UIColor.yellowColor()
let screenSize: CGRect = UIScreen.mainScreen().bounds
v.frame.size = CGSize(width: screenSize.width - 10, height: CGFloat(160))
v.frame.origin = Point
let vid = UIImageView()
vid.image = UIImage(named: "default")
vid.backgroundColor = UIColor.grayColor()
vid.contentMode = .ScaleAspectFill
vid.af_setImageWithURL(NSURL(string: "Image HTTP url")!)
vid.frame.size = v.frame.size
vid.frame.origin = CGPoint(x: 0, y: 0)
vid.clipsToBounds = true
vid.userInteractionEnabled = true
v.userInteractionEnabled = true
let tapRecognizer = UITapGestureRecognizer(target: self, action: Selector("imageTapped:"))
vid.addGestureRecognizer(tapRecognizer)
v.addSubview(vid)
}
func imageTapped(gestureRecognizer: UITapGestureRecognizer) {
//Not detected to here
}
}
And when I tap on image the following error occurred:
NSForwarding: warning: object 0x7c8cc830 of class 'MSC_CLItem_Tizer' does not implement methodSignatureForSelector: -- trouble ahead
Unrecognized selector -[MSC_CLItem_Tizer imageTapped:]
I'm very confused of which section of my code is wrong?
Thank you
You must declare the super class as NSObject
class MSC_CLItem : NSObject
{
......
}
let tapRecognizer = UITapGestureRecognizer(target: self, action: Selector("imageTapped:"))
tapGesture.numberOfTouchesRequired = 1;
tapGesture.numberOfTapsRequired = 1;
vid.addGestureRecognizer(tapRecognizer)
v.addSubview(vid)
self.view.addSubview(v)
For more details
Does not implement methodSignatureForSelector: — trouble ahead
Got Unrecognized selector -replacementObjectForKeyedArchiver: crash when implementing NSCoding in Swift [Xcode 6 GM]
I guess here can be a problem. Write this line without ":"
let tapRecognizer = UITapGestureRecognizer(target: self, action: Selector("imageTapped"))

Resources