Detect hash tags #, mention tags @, in iOS like in

2019-01-13 23:39发布

问题:

I need to Detect #Tags given in description UILabel and change text color as [UIColor BlueColor]; where i am not able to change particular text colors in UILabel to Blue. Now i am Using this UILabel in custom UITableViewCell. is there any way to solve this issue to differentiate #Tags and normal text by Text Colors ? can anybody help me to solve this ?

回答1:

-(NSMutableAttributedString*)decorateTags:(NSString *)stringWithTags{


    NSError *error = nil;

    //For "Vijay #Apple Dev"
    NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"#(\\w+)" options:0 error:&error];

    //For "Vijay @Apple Dev"
    //NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"@(\\w+)" options:0 error:&error];

    NSArray *matches = [regex matchesInString:stringWithTags options:0 range:NSMakeRange(0, stringWithTags.length)];
    NSMutableAttributedString *attString=[[NSMutableAttributedString alloc] initWithString:stringWithTags];

    NSInteger stringLength=[stringWithTags length];

    for (NSTextCheckingResult *match in matches) {

        NSRange wordRange = [match rangeAtIndex:1];

        NSString* word = [stringWithTags substringWithRange:wordRange];

        //Set Font
        UIFont *font=[UIFont fontWithName:@"Helvetica-Bold" size:15.0f];
        [attString addAttribute:NSFontAttributeName value:font range:NSMakeRange(0, stringLength)];


        //Set Background Color
        UIColor *backgroundColor=[UIColor orangeColor];
        [attString addAttribute:NSBackgroundColorAttributeName value:backgroundColor range:wordRange];

        //Set Foreground Color
        UIColor *foregroundColor=[UIColor blueColor];
        [attString addAttribute:NSForegroundColorAttributeName value:foregroundColor range:wordRange];

        NSLog(@"Found tag %@", word);

    }

    // Set up your text field or label to show up the result

    //    yourTextField.attributedText = attString;
    //
    //    yourLabel.attributedText = attString;

    return attString;
}



回答2:

New : Use this link in iOS 9 https://github.com/hsusmita/ResponsiveLabel

Old : Use this Its customizable as well https://github.com/SebastienThiebaud/STTweetLabel



回答3:

Here's a Swift solution. It uses UITextView which supports attributed text, multiline, and supports the built-in delegate to map tap events to the selected words (which users might expect when they see blue text).

Rather than changing the range of characters to .blueColor(), it adds a link attribute which automatically sets the clickable text to your global tint.

It also contains some basic support for Twitter hashtag rules for handling numbers #1 and special characters @abc.go.

Working sample project:

https://github.com/ThornTechPublic/SwiftTextViewHashtag/blob/master/textViewSample/UITextField%2BExtension.swift

Blog post with a more generic explanation:

http://www.thorntech.com/2015/06/detecting-hashtags-mentions-and-urls-with-swift/

extension UITextView {

    func chopOffNonAlphaNumericCharacters(text:String) -> String {
        var nonAlphaNumericCharacters = NSCharacterSet.alphanumericCharacterSet().invertedSet
        let characterArray = text.componentsSeparatedByCharactersInSet(nonAlphaNumericCharacters)
        return characterArray[0]
    }

    /// Call this manually if you want to hash tagify your string.
    func resolveHashTags(){

        let schemeMap = [
            "#":"hash",
            "@":"mention"
        ]

        // Turn string in to NSString.
        // NSString gives us some helpful API methods
        let nsText:NSString = self.text

        // Separate the string into individual words.
        // Whitespace is used as the word boundary.
        // You might see word boundaries at special characters, like before a period.
        // But we need to be careful to retain the # or @ characters.
        let words:[NSString] = nsText.componentsSeparatedByCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet()) as! [NSString]

        // Attributed text overrides anything set in the Storyboard.
        // So remember to set your font, color, and size here.
        var attrs = [
//            NSFontAttributeName : UIFont(name: "Georgia", size: 20.0)!,
//            NSForegroundColorAttributeName : UIColor.greenColor(),
            NSFontAttributeName : UIFont.systemFontOfSize(17.0)
        ]

        // Use an Attributed String to hold the text and fonts from above.
        // We'll also append to this object some hashtag URLs for specific word ranges.
        var attrString = NSMutableAttributedString(string: nsText as String, attributes:attrs)

        // Iterate over each word.
        // So far each word will look like:
        // - I
        // - visited
        // - #123abc.go!
        // The last word is a hashtag of #123abc
        // Use the following hashtag rules:
        // - Include the hashtag # in the URL
        // - Only include alphanumeric characters.  Special chars and anything after are chopped off.
        // - Hashtags can start with numbers.  But the whole thing can't be a number (#123abc is ok, #123 is not)
        for word in words {

            var scheme:String? = nil

            if word.hasPrefix("#") {
                scheme = schemeMap["#"]
            } else if word.hasPrefix("@") {
                scheme = schemeMap["@"]
            }

            // found a word that is prepended by a hashtag
            if let scheme = scheme {

                // convert the word from NSString to String
                // this allows us to call "dropFirst" to remove the hashtag
                var stringifiedWord:String = word as String

                // example: #123abc.go!

                // drop the hashtag
                // example becomes: 123abc.go!
                stringifiedWord = dropFirst(stringifiedWord)

                // Chop off special characters and anything after them.
                // example becomes: 123abc
                stringifiedWord = chopOffNonAlphaNumericCharacters(stringifiedWord)

                if let stringIsNumeric = stringifiedWord.toInt() {
                    // don't convert to hashtag if the entire string is numeric.
                    // example: 123abc is a hashtag
                    // example: 123 is not
                } else if stringifiedWord.isEmpty {
                    // do nothing.
                    // the word was just the hashtag by itself.
                } else {
                    // set a link for when the user clicks on this word.
                    var matchRange:NSRange = nsText.rangeOfString(stringifiedWord as String)
                    // Remember, we chopped off the hash tag, so:
                    // 1.) shift this left by one character.  example becomes:  #123ab
                    matchRange.location--
                    // 2.) and lengthen the range by one character too.  example becomes:  #123abc
                    matchRange.length++
                    // URL syntax is http://123abc

                    // Replace custom scheme with something like hash://123abc
                    // URLs actually don't need the forward slashes, so it becomes hash:123abc
                    // Custom scheme for @mentions looks like mention:123abc
                    // As with any URL, the string will have a blue color and is clickable
                    attrString.addAttribute(NSLinkAttributeName, value: "\(scheme):\(stringifiedWord)", range: matchRange)
                }
            }

        }

        // Use textView.attributedText instead of textView.text
        self.attributedText = attrString
    }

}

Usage:

textView.resolveHashTags()

To handle the tap event:

func showHashTagAlert(tagType:String, payload:String){
    let alertView = UIAlertView()
    alertView.title = "\(tagType) tag detected"
    // get a handle on the payload
    alertView.message = "\(payload)"
    alertView.addButtonWithTitle("Ok")
    alertView.show()
}

extension ViewController : UITextViewDelegate {

    func textView(textView: UITextView, shouldInteractWithURL URL: NSURL, inRange characterRange: NSRange) -> Bool {

        // check for our fake URL scheme hash:helloWorld
        if let scheme = URL.scheme {
            switch scheme {
            case "hash" :
                showHashTagAlert("hash", payload: URL.resourceSpecifier!)
            case "mention" :
                showHashTagAlert("mention", payload: URL.resourceSpecifier!)
            default:
                println("just a regular url")
            }
        }

        return true
    }

}


回答4:

You can use https://github.com/Krelborn/KILabel this library. It also detect user taps on hashtags Like this:

label.hashtagLinkTapHandler = ^(KILabel *label, NSString *string, NSRange range) {
  NSLog(@"Hashtag tapped %@", string);
};