Search code examples
iosswiftuitextviewnsattributedstringuitextviewdelegate

AttributedText in TextView while typing


I have a textView, and I am trying to give it an attributed text. I tried achieving it inside shouldChangeTextInRange, but it crashes for range out of index.

func textView(textView: UITextView, shouldChangeTextInRange range: NSRange, replacementText text: String) -> Bool { 

   if myTextView {
      textView.attributedText = addAttributedText(1, text: text, fontsize: 13)

      let newText = (textView.text as NSString).stringByReplacingCharactersInRange(range, withString: text)
      let numberOfChars = newText.characters.count

      return numberOfChars < 20
   }
   return true
}

 func addAttributedText(spacing:CGFloat, text:String, fontsize: CGFloat) -> NSMutableAttributedString {
    let attributedString = NSMutableAttributedString(string: text, attributes: [NSFontAttributeName:UIFont(
        name: "Font",
        size: fontsize)!])
    attributedString.addAttribute(NSKernAttributeName, value: spacing, range: NSMakeRange(0, text.characters.count))
    return attributedString

}

I tried adding attributedString with empty text to textView in viewDidLoad, but that doesn't help. That's why I thought it would be appropriate to do it on shouldChangeTextInRange

(Please note that my addAttributedText method works perfectly for other textviews)

If I use this, in one character type-in, it writes 2x and crashes. What is the right way of handling that kind of converting textView's text to attributed text that is being typed.


Solution

  • Here is the code that I tried to convert from the link above, it might have bugs, but I hope it will be able to help you.

    func formatTextInTextView(textView: UITextView) 
    {
        textView.scrollEnabled = false
        var selectedRange: NSRange = textView.selectedRange
        var text: String = textView.text!
        // This will give me an attributedString with the base text-style
        var attributedString: NSMutableAttributedString = NSMutableAttributedString(string: text)
        var error: NSError? = nil
        var regex: NSRegularExpression = NSRegularExpression.regularExpressionWithPattern("#(\\w+)", options: 0, error: error!)
        var matches: [AnyObject] = regex.matchesInString(text, options: 0, range: NSMakeRange(0, text.length))
    
        for match: NSTextCheckingResult in matches {
            var matchRange: NSRange = match.rangeAtIndex(0)
            attributedString.addAttribute(NSForegroundColorAttributeName, value: UIColor.redColor(), range: matchRange)
        }
        textView.attributedText = attributedString
        textView.selectedRange = selectedRange
        textView.scrollEnabled = true
    }
    

    EDIT: didn't see that in the original post there was a Swift answer, here is the link: stackoverflow.com/a/35842523/1226963