I have developed a UIView from For loop and basically it is create 3 Views from loop. and I have to add touch gesture on every View to call a method but I am unable to get current selected UIView.tag when I tap on it. it is only showing the .tag of the last view. here is my code.
for i in 0 ... 2 {
let productView = UIView()
productView.tag = i
productView.isUserInteractionEnabled = true
let producttap = UITapGestureRecognizer(target: self, action: #selector(self.ProductTapped))
productView.addGestureRecognizer(producttap)
productView.frame = CGRect(x: xOffset, y: CGFloat(buttonPadding), width: 200, height: scView1.frame.size.height)
xOffset = xOffset + CGFloat(buttonPadding) + productView.frame.size.width
scView1.addSubview(productView)
productIndex = productView.tag
}
and here is the method that I am calling from every UIView touch.
#objc func ProductTapped() {
print("",productIndex)
}
Your code should be using delegate/callback closure, but if you want to keep using tag, try change it to:
#objc func ProductTapped(_ sender: UITapGestureRecognizer) {
if let view = sender.view {
print(view.tag)
}
}
and the gesture attach to let producttap = UITapGestureRecognizer(target: self, action: #selector(self.ProductTapped(_:)))
productIndex does nothing here since it got overwritten on the loop
productIndex currently has no relationship to the tap gestures that you attach your views. You do set productIndex in the the loop but that's irrelevant to your gesture.
Perhaps you want
let producttap = UITapGestureRecognizer(target: self, action: #selector(productTapped(_:))
and
#objc func productTapped(_ gesture: UITapGestureRecognizer) {
print("tag is",gesture.view.tag)
}
I've got an array of UIImageViews and have programmatically assigned tap gesture recognizers to them.
myImages.forEach{ UIImageView in
let tap = UITapGestureRecognizer(target: self, action: #selector(handleTap(gesture:)))
tap.numberOfTapsRequired = 1
tap.delegate = self
view.addGestureRecognizer(tap)
}
What's the best way to assign a sender to each (or determine which image was tapped another way)? I've unsuccessfully tried
var tag = sender.view!.tag
Thanks!
in here you need to follow two steps,
step 1
assign the tags for imageview before append to your myImages array.
step 2
get the tag from imageview array and assign to your each gesture
myImages.forEach{
let tap = UITapGestureRecognizer(target: self, action: #selector(handleTap(_:)))
tap.numberOfTapsRequired = 1
tap.view?.tag = $0.tag
$0.isUserInteractionEnabled = true
$0.addGestureRecognizer(tap)
}
and handle the func like
#objc func handleTap(_ sender: UITapGestureRecognizer) {
guard let getTag = sender.view?.tag else { return }
print("getTag == \(getTag)")
}
You can use the block provided by UITapGestureRecognizer init to access your images in place.
myImages.forEach { image in
let tap = UITapGestureRecognizer(block: {[weak self] _ in
//Do your stuff here
//print("Image Tapped:", image.debugDescription)
}, delegate: self)
tap.numberOfTapsRequired = 1
image.addGestureRecognizer(tap)
}
If you want to set UITapGestureRecognizer in UICollectionView or UITableView cell then below solution is useful for us.
Step 1 Assign the UITapGestureRecognizer to particuller textview or other view in UICollectionView or UITableView cell.
cell.textView?.delegate = self
cell.textView?.isEditable = false
cell.textView?.isSelectable = true
let tap = UITapGestureRecognizer(target: self, action:#selector(self.onclickLink(_:)))
cell.textView?.tag = indexPath.row
tap.numberOfTapsRequired = 1
cell.textView?.addGestureRecognizer(tap)
Step 2 Get the tag from UITextView or other View in onclick action.
#IBAction func onclickLink(_ sender: UITapGestureRecognizer) {
print("indexPathRow == \(sender.view?.tag ?? 0)")
}
I would like to ask on how to add a parameter on the UITapGestureRecognizer on my UILabel. So far this is what I got:
self.feedSource.text = source_link
self.feedSource.userInteractionEnabled = true
let feedSourceTapGesture = UITapGestureRecognizer(target: self, action: Selector("openLinkFromFeedSource"))
self.feedSource.addGestureRecognizer(feedSourceTapGesture)
func openLinkFromFeedSource() {
print("tapped")
}
What I want to achieve is when I tapped the label, from openLinkFromFeedSource I can get the value of the self.feedSource.text
Thanks!
You should get this from tap gesture action like this:
func didTapOnView(tap: UITapGestureRecognizer) {
let label = tap.view
// do with that label
}
try this
self.feedSource.userInteractionEnabled = true
let feedSourceTapGesture = UITapGestureRecognizer(target: self, action: Selector("openLinkFromFeedSource:"))
self.feedSource.addGestureRecognizer(feedSourceTapGesture)
func openLinkFromFeedSource(sender: UITapGestureRecognizer) {
let label = sender.view
print("tapped")
}
I have the next code
var i = 0
for answer in answeres{
let singleTap = UITapGestureRecognizer(target: self, action:#selector(tapDetected(_:))
imageView.addGestureRecognizer(singleTap)
i+=1
}
func tapDetected(position : Int) {
print(position)
}
How can I pass the var 'i' to each imageView, so when the user click the imageView, it prints the correct number in the log?
The method called by the recognizer is passed the recognizer as a first argument:
func tapDetected(sender: UITapGestureRecognizer) {}
Which means you can use the view property of the recognizer to access the view associated with it. And the number can be stored as the view tag:
var i = 0
for answer in answers {
let singleTap = …
let imageView = …
imageView.addGestureRecognizer(singleTap)
imageView.tag = i
i = i + 1
}
func tapDetected(sender: UITapGestureRecognizer) {
print(sender.view.tag)
}
I have discovered that I can create UILabel much faster than UITextField and I plan to use UILabel most of the time for my data display app.
To make a long story short though, I wish to let the user tap on a UILabel and have my callback respond to that. Is that possible?
Thanks.
You can add a UITapGestureRecognizer instance to your UILabel.
For example:
UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(labelTapped)];
tapGestureRecognizer.numberOfTapsRequired = 1;
[myLabel addGestureRecognizer:tapGestureRecognizer];
myLabel.userInteractionEnabled = YES;
If you're using storyboards you can do this entire process in the storyboard with no additional code. Add a label to the storyboard, then add a tap gesture to the label. In the Utilities pane, make sure "User Interaction Enabled" is checked for the label. From the tap gesture (at the bottom of your view controller in the storyboard), ctrl+click and drag to your ViewController.h file and create an Action. Then implement the action in the ViewController.m file.
Swift 3.0
Initialize the gesture for tempLabel
tempLabel?.text = "Label"
let tapAction = UITapGestureRecognizer(target: self, action: #selector(self.actionTapped(_:)))
tempLabel?.isUserInteractionEnabled = true
tempLabel?.addGestureRecognizer(tapAction)
Action receiver
func actionTapped(_ sender: UITapGestureRecognizer) {
// code here
}
Swift 4.0
Initialize the gesture for tempLabel
tempLabel?.text = "Label"
let tapAction = UITapGestureRecognizer(target: self, action:#selector(actionTapped(_:)))
tempLabel?.isUserInteractionEnabled = true
tempLabel?.addGestureRecognizer(tapAction)
Action receiver
func actionTapped(_ sender: UITapGestureRecognizer) {
// code here
}
Swift 2.0:
I am adding a nsmutable string as sampleLabel's text, enabling user interaction, adding a tap gesture and trigger a method.
override func viewDidLoad() {
super.viewDidLoad()
let newsString: NSMutableAttributedString = NSMutableAttributedString(string: "Tap here to read the latest Football News.")
newsString.addAttributes([NSUnderlineStyleAttributeName: NSUnderlineStyle.StyleDouble.rawValue], range: NSMakeRange(4, 4))
sampleLabel.attributedText = newsString.copy() as? NSAttributedString
let tapGesture: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: "tapResponse:")
tapGesture.numberOfTapsRequired = 1
sampleLabel.userInteractionEnabled = true
sampleLabel.addGestureRecognizer(tapGesture)
}
func tapResponse(recognizer: UITapGestureRecognizer) {
print("tap")
}
You could use a UIButton instead and set the text to what you want. The button doesn't have to look like a button if you don't want to
To add Tap gesture on UILable
UITapGestureRecognizer *tapAction = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(lblClick:)];
tapAction.delegate =self;
tapAction.numberOfTapsRequired = 1;
//Enable the lable UserIntraction
lblAction.userInteractionEnabled = YES;
[lblAction addGestureRecognizer:tapAction];
and to assess the selector method
- (void)lblClick:(UITapGestureRecognizer *)tapGesture {
}
Note: Add UIGestureRecognizerDelegate in .h file
Swift Version:
var tapGesture : UITapGestureRecognizer = UITapGestureRecognizer()
Then inside viewDidLoad(),add this:
let yourLbl=UILabel(frame: CGRectMake(x,y,width,height)) as UILabel!
yourLbl.text = "SignUp"
tapGesture.numberOfTapsRequired = 1
yourLbl.addGestureRecognizer(tapGesture)
yourLbl.userInteractionEnabled = true
tapGesture.addTarget(self, action: "yourLblTapped:")
This works great in Xcode 12 and Swift 5
let tapAction = UITapGestureRecognizer(target: self,action:#selector(actionTapped(_:)))
userLabel?.isUserInteractionEnabled = true
userLabel?.addGestureRecognizer(tapAction)
And action method like -
#objc func actionTapped(_ sender: UITapGestureRecognizer) {
print("tapped")
}
If you want to use Multi line text in your button then create a UILabel with Multiline text and add as a subview in to your button.
for eg:
yourLabel=[Uilabel alloc]init];
yourLabel.frame=yourButtom.Frame;//(frame size should be equal to your button's frame)
[yourButton addSubView:yourLabel]
Swift 3 from Alvin George
override func viewDidLoad() {
super.viewDidLoad()
let newsString: NSMutableAttributedString = NSMutableAttributedString(string: "Tap here to read the latest Football News.")
newsString.addAttributes([NSUnderlineStyleAttributeName: NSUnderlineStyle.styleDouble.rawValue], range: NSMakeRange(4, 4))
sampleLabel.attributedText = newsString.copy() as? NSAttributedString
let tapGesture: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(ViewController.tapResponse))
tapGesture.numberOfTapsRequired = 1
sampleLabel.isUserInteractionEnabled = true
sampleLabel.addGestureRecognizer(tapGesture)
}
func tapResponse(recognizer: UITapGestureRecognizer) {
print("tap")
}
Swift version looks like this:
func addGestureRecognizerLabel(){
//Create a instance, in this case I used UITapGestureRecognizer,
//in the docs you can see all kinds of gestures
let gestureRecognizer = UITapGestureRecognizer()
//Gesture configuration
gestureRecognizer.numberOfTapsRequired = 1
gestureRecognizer.numberOfTouchesRequired = 1
/*Add the target (You can use UITapGestureRecognizer's init() for this)
This method receives two arguments, a target(in this case is my ViewController)
and the callback, or function that you want to invoke when the user tap it view)*/
gestureRecognizer.addTarget(self, action: "showDatePicker")
//Add this gesture to your view, and "turn on" user interaction
dateLabel.addGestureRecognizer(gestureRecognizer)
dateLabel.userInteractionEnabled = true
}
//How you can see, this function is my "callback"
func showDatePicker(){
//Your code here
print("Hi, was clicked")
}
//To end just invoke to addGestureRecognizerLabel() when
//your viewDidLoad() method is called
override func viewDidLoad() {
super.viewDidLoad()
addGestureRecognizerLabel()
}
I personally prefer the method of writing an extension for UILabel. This is what I use.
import UIKit
extension UILabel {
/**
* A map of actions, mapped as [ instanceIdentifier : action ].
*/
private static var _tapHandlers = [String:(()->Void)]()
/**
* Retrieve the address for this UILabel as a String.
*/
private func getAddressAsString() -> String {
let addr = Unmanaged.passUnretained(self).toOpaque()
return "\(addr)"
}
/**
* Set the on tapped event for the label
*/
func setOnTapped(_ handler: #escaping (()->Void)) {
UILabel._tapHandlers[getAddressAsString()] = handler
let gr = UITapGestureRecognizer(target: self, action: #selector(onTapped))
gr.numberOfTapsRequired = 1
self.addGestureRecognizer(gr)
self.isUserInteractionEnabled = true
}
/**
* Handle the tap event.
*/
#objc private func onTapped() {
UILabel._tapHandlers[self.getAddressAsString()]?()
}
}
You would then use it like this from any UILabel instance:
myLabel.setOnTapped {
// do something
}
This can potentially cause some memory leaks I believe, but I haven't determined how best to resolve them yet.