Reputation: 1021
I am using this Extension to detect Hashtags inside a UILabel:
import UIKit
extension UILabel {
func resolveHashTags(){
// turn string in to NSString
let nsText:NSString = self.text!
// this needs to be an array of NSString. String does not work.
let words:[NSString] = nsText.componentsSeparatedByString(" ")
// you can't set the font size in the storyboard anymore, since it gets overridden here.
let attrs = [
NSFontAttributeName : UIFont.systemFontOfSize(17.0)
]
// you can staple URLs onto attributed strings
let attrString = NSMutableAttributedString(string: nsText as String, attributes:attrs)
// tag each word if it has a hashtag
for word in words {
// found a word that is prepended by a hashtag!
// homework for you: implement @mentions here too.
if word.hasPrefix("#") {
// a range is the character position, followed by how many characters are in the word.
// we need this because we staple the "href" to this range.
let matchRange:NSRange = nsText.rangeOfString(word as String)
// convert the word from NSString to String
// this allows us to call "dropFirst" to remove the hashtag
var stringifiedWord:String = word as String
// drop the hashtag
stringifiedWord = String(stringifiedWord.characters.dropFirst())
// check to see if the hashtag has numbers.
// ribl is "#1" shouldn't be considered a hashtag.
let digits = NSCharacterSet.decimalDigitCharacterSet()
if let numbersExist = stringifiedWord.rangeOfCharacterFromSet(digits) {
// hashtag contains a number, like "#1"
// so don't make it clickable
} else {
// set a link for when the user clicks on this word.
// it's not enough to use the word "hash", but you need the url scheme syntax "hash://"
// note: since it's a URL now, the color is set to the project's tint color
attrString.addAttribute(NSLinkAttributeName, value: "hash:\(stringifiedWord)", range: matchRange)
}
}
}
self.attributedText = attrString
}
}
To use this, i do this:
self.myLabel.resolveHashTags()
But, how can i detect when a hashtag is tapped, and they do a print("hashtag clicked")
?
Does anyone has any idea or suggestions on how i can do this?
Upvotes: 1
Views: 2073
Reputation: 765
let label: UILabel = ... //This could possibly be an IBOutlet, or however you want to attempt to get a reference to the label
label.userInteractionEnabled = true //You have to enable user interaction on labels
let tapGesture = UITapGestureRecognizer(target: self, action: "labelTap:") //Create a tap gesture
label.addGestureRecognizer(tapGesture) //Set the labels gesture
At this point, you will need a labelTap function in your class. We will also need to make sure the function has a variable with it (notice how the action on the tapGesture includes a colon, thus suggesting that a variable is in the function).
It would look something like this:
func labelTap(gestureRecognizer: UIGestureRecognizer) {
//This function will be called everytime your label is called
}
At this point you just add the needed logic into the labelTap function.
Edit: In response to your comment, here is some relevant code on how to check if there is, indeed, a hashtag in the label (This code is just adapted from your original resolveHashTags() function):
func labelTap(gestureRecognizer: UIGestureRecognizer) {
// turn string in to NSString
let nsText:NSString = label.text!
// this needs to be an array of NSString. String does not work.
let words:[NSString] = nsText.componentsSeparatedByString(" ")
// tag each word if it has a hashtag
for word in words {
// found a word that is prepended by a hashtag!
// homework for you: implement @mentions here too.
if word.hasPrefix("#") {
// a range is the character position, followed by how many characters are in the word.
// we need this because we staple the "href" to this range.
let matchRange:NSRange = nsText.rangeOfString(word as String)
// convert the word from NSString to String
// this allows us to call "dropFirst" to remove the hashtag
var stringifiedWord:String = word as String
// drop the hashtag
stringifiedWord = String(stringifiedWord.characters.dropFirst())
// check to see if the hashtag has numbers.
// ribl is "#1" shouldn't be considered a hashtag.
let digits = NSCharacterSet.decimalDigitCharacterSet()
if let numbersExist = stringifiedWord.rangeOfCharacterFromSet(digits) {
// hashtag contains a number, like "#1"
// so don't make it clickable
} else {
// a hashtag was clicked!
print("A hashtag was clicked. The hashtag was: \(stringifiedWord)")
}
}
}
}
Upvotes: 0
Reputation: 118691
You can implement the UITextViewDelegate method textView(_:shouldInteractWithURL URL:inRange:)
which allows you to handle the link being clicked:
func textView(_ textView: UITextView, shouldInteractWithURL URL: NSURL, inRange characterRange: NSRange) -> Bool {
// ...check that this is a hashtag link, and not a regular link...
print("hashtag clicked")
}
Upvotes: 1