How to 'addTarget' to UILabel in Swift
Asked Answered
D

2

12

I am trying to add labels in Swift, which are added in a loop. I then want to add a 'TapGesture' event to each one as they are added. It works , but the problem is that the function called takes data from the label to use when it's clicked, but the label has been redefined by then and it takes data from the last one added, not the one that was clicked. How can I make each one unique?

self.label.attributedText = self.myMutableString
let tapGesture = UITapGestureRecognizer(target: self, action: handleTap(label))
self.label.userInteractionEnabled=true
self.label.addGestureRecognizer(tapGesture)
self.label.font = UIFont.boldSystemFontOfSize(28)
self.label.sizeToFit()
self.label.center = CGPoint(x: screenWidth, y: top)
if(kilom>=30||self.located==false){
    self.scroller.addSubview(self.label)
    if(device=="iPhone"||device=="iPhone Simulator"){
        top = top+80
    }
    else{
        top = top+140
    }
}

The code below is the gesture recognizer that gets the label data and uses it:

func handleTap(sender:UILabel){
    var a = self.label.text
    let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil)

    let resultViewController = storyBoard.instantiateViewControllerWithIdentifier("displayer") 

    self.presentViewController(resultViewController, animated: true, completion: nil)
}
Defiance answered 4/6, 2016 at 13:42 Comment(1)
From the code you posted, it seems that you only have one label. You change its attributes but you don't create a new one (unless it's in code that you didn't include).Wheedle
S
17

The handler function for a UITapGestureRecognizer is passed the UITapGestureRecognizer as the sender. You can access the view that it is attached to with the view property. I would suggest something like this:

func handleTap(sender: UITapGestureRecognizer) {
    guard let a = (sender.view as? UILabel)?.text else { return }

    ...
}

You will also need to change the signature of your selector:

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

or for earlier versions of Swift:

let tapGesture = UITapGestureRecognizer(target: self, action: "handleTap:")
Spoil answered 4/6, 2016 at 14:0 Comment(10)
I am now having the trouble of adding a value for an undefinedkey for each label? I am trying to store data in that but keep getting an error saying "UncaughtNSException" and " this is not a key coding complaint"Defiance
What are you trying to do? Update the text of the label? Can you show the line of code giving you the error?Spoil
No, when the label is clicked, I want the handletap function to get data from the label, (which I want to store when it is created): self.label.setValue(data[0], forUndefinedKey: "name") The error is: NSUnknownKeyException', reason: '[ setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key timelineTableDefiance
A label is a UI element. You really shouldn't be trying to store data there. If you want to associate data with a label, you could assign a tag value (which is an Int) to the label and then use that tag to access data in an array of structs or a dictionary.Spoil
Well, I'm only trying to store the data in the label for when it is later needed to be saved (when the label is clicked). but how do I assign a tag value then?Defiance
label.tag = 15. Just give each label a unique tag when you create it, and store the value you are trying to save/retrieve in a dictionary that is a property of your viewController. myDict[tag] = "valueToRetrieveLater". In handleTap: guard let tag = sender.view?.tag else { return } and if let valueToSave = myDict[tag] { // save the value }.Spoil
Okay, I understand most of it and have no errors. but what is myDict? i.e. How do i define it?Defiance
Just put var myDict = [Int: String]() as a property of your viewController. That assumes you're storing a String. Change it to whatever type of data you are storing.Spoil
You're welcome. I also answered your line question from yesterday.Spoil
I like this approach, but this doesn't work (as far as I can see) when the labels are part of a UITableViewCell; once a cell is reused, the saved tag no longer be associated with the label, correct?Lorri
B
6

SWIFT 5.1

Great answer by @vacawana but I just want to post what a complete code will look like to help a bit. You need to add a isUserInteractionEnabled to the label.. as well as the tapGesture created.

let label = UILabel()
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTap))

label.isUserInteractionEnabled = true
label.addGestureRecognizer(tapGesture)
return label

Don't forget to add @objc before "func handleTap"

Brost answered 20/2, 2021 at 20:0 Comment(1)
Thanks for the cookbook recipe. Saves time.Malonis

© 2022 - 2024 — McMap. All rights reserved.