How to make UITextView detect hashtags?

后端 未结 4 1453
野的像风
野的像风 2021-01-31 22:39

I know that the UITextView default can detect URL, but how can i make it detect hashtags(#)?

It doesn\'t needs to detect hashtags while typing, but then

相关标签:
4条回答
  • 2021-01-31 22:57

    One option would be to use an NSAttributedString, something like this...

    func convertHashtags(text:String) -> NSAttributedString {
        let attrString = NSMutableAttributedString(string: text)
        attrString.beginEditing()
        // match all hashtags
        do {
            // Find all the hashtags in our string
            let regex = try NSRegularExpression(pattern: "(?:\\s|^)(#(?:[a-zA-Z].*?|\\d+[a-zA-Z]+.*?))\\b", options: NSRegularExpressionOptions.AnchorsMatchLines)
            let results = regex.matchesInString(text,
                options: NSMatchingOptions.WithoutAnchoringBounds, range: NSMakeRange(0, text.characters.count))
            let array = results.map { (text as NSString).substringWithRange($0.range) }
            for hashtag in array {
                // get range of the hashtag in the main string
                let range = (attrString.string as NSString).rangeOfString(hashtag)
                // add a colour to the hashtag
                attrString.addAttribute(NSForegroundColorAttributeName, value: UIColor.redColor() , range: range)
            }
            attrString.endEditing()
        }
        catch {
            attrString.endEditing()
        }
        return attrString
    }
    

    Then assign your attributedText like this...

    let myText = "some text with a #hashtag in side of it #itsnoteasy"
    self.textView.attributedText = convertHashtags(myText)
    
    0 讨论(0)
  • 2021-01-31 23:12

    This should work for you

    1. Create a new swift file with any name(UITextViewHashtagExtension.swift)
    2. Insert this code below:

      import UIKit
      
      extension UITextView {
      
      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)
                  }
      
              }
          }
      
          // we're used to textView.text
          // but here we use textView.attributedText
          // again, this will also wipe out any fonts and colors from the storyboard,
          // so remember to re-add them in the attrs dictionary above
          self.attributedText = attrString
      }
      
      }
      

    To use this you can do something like this:

    self.textView.text = "This is an #example test"
    self.textView.resolveHashTags()
    

    Updated for Swift 4.0:

    extension UITextView {
    
        func resolveHashTags() {
    
            // turn string in to NSString
            let nsText = NSString(string: self.text)
    
            // this needs to be an array of NSString.  String does not work.
            let words = nsText.components(separatedBy: CharacterSet(charactersIn: "#ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_").inverted)
    
            // you can staple URLs onto attributed strings
            let attrString = NSMutableAttributedString()
            attrString.setAttributedString(self.attributedText)
    
            // tag each word if it has a hashtag
            for word in words {
                if word.count < 3 {
                    continue
                }
    
                // 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.range(of: word as String)
    
                    // drop the hashtag
                    let stringifiedWord = word.dropFirst()
                    if let firstChar = stringifiedWord.unicodeScalars.first, NSCharacterSet.decimalDigits.contains(firstChar) {
                        // 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(NSAttributedStringKey.link, value: "hash:\(stringifiedWord)", range: matchRange)
                    }
    
                }
            }
    
            // we're used to textView.text
            // but here we use textView.attributedText
            // again, this will also wipe out any fonts and colors from the storyboard,
            // so remember to re-add them in the attrs dictionary above
            self.attributedText = attrString
        }
    }
    
    0 讨论(0)
  • 2021-01-31 23:16

    For Swift 3 +

     extension UITextView {
            
            func convertHashtags(text:String) -> NSAttributedString {
                
                let attr = [
                    NSFontAttributeName : UIFont.systemFont(ofSize: 17.0),
                    NSForegroundColorAttributeName : clr_golden,    
                    NSLinkAttributeName : "https://Laitkor.com"
                 ] as [String : Any]
    
            
            let attrString = NSMutableAttributedString(string: text)
            attrString.beginEditing()
            // match all hashtags
            do {
                // Find all the hashtags in our string
                let regex = try NSRegularExpression(pattern: "(?:\\s|^)(#(?:[a-zA-Z].*?|\\d+[a-zA-Z]+.*?))\\b", options: NSRegularExpression.Options.anchorsMatchLines)
                let results = regex.matches(in: text,
                                                    options: NSRegularExpression.MatchingOptions.withoutAnchoringBounds, range: NSMakeRange(0, text.characters.count))
                let array = results.map { (text as NSString).substring(with: $0.range) }
                for hashtag in array {
                    // get range of the hashtag in the main string
                    let range = (attrString.string as NSString).range(of: hashtag)
                    // add a colour to the hashtag
                    //attrString.addAttribute(NSForegroundColorAttributeName, value: clr_golden , range: range)
                    attrString.addAttributes(attr, range: range)
                }
                attrString.endEditing()
            }
            catch {
                attrString.endEditing()
            }
            return attrString
        }
    }
    

    Add UITextViewDelegate in your class and Use like this

     self.tv_yourTextView.delegate = self
     self.tv_yourTextView.attributedText = tv_yourTextView.convertHashtags(text: "This is an #museer test")
    

    delegate funtion

    func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange) -> Bool {
        print("hastag Selected!")
        return true
    }
    

    -> Modified @Wez Answer

    0 讨论(0)
  • 2021-01-31 23:20

    For swift 4.0

    extension UITextView {
    
        func resolveHashTags() {
    
            // turn string in to NSString
            let nsText = NSString(string: self.text)
    
            // this needs to be an array of NSString.  String does not work.
            let words = nsText.components(separatedBy: CharacterSet(charactersIn: "#ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_").inverted)
    
            // you can staple URLs onto attributed strings
            let attrString = NSMutableAttributedString()
            attrString.setAttributedString(self.attributedText)
    
            // tag each word if it has a hashtag
            for word in words {
                if word.count < 3 {
                    continue
                }
    
                // 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.range(of: word as String)
    
                    // drop the hashtag
                    let stringifiedWord = word.dropFirst()
                    if let firstChar = stringifiedWord.unicodeScalars.first, NSCharacterSet.decimalDigits.contains(firstChar) {
                        // 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(NSAttributedStringKey.link, value: "hash:\(stringifiedWord)", range: matchRange)
                    }
    
                }
            }
    
            // we're used to textView.text
            // but here we use textView.attributedText
            // again, this will also wipe out any fonts and colors from the storyboard,
            // so remember to re-add them in the attrs dictionary above
            self.attributedText = attrString
        }
    }
    
    0 讨论(0)
提交回复
热议问题