简体   繁体   中英

Detect click hashtag in UILabel

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?

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")
}
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)")
            }

        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM