senty senty - 1 year ago 144
Swift Question

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.

Answer Source

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