Can I use a String
and NSMutableAttributedString
in the same UITextView
?
I am importing a .docx
file and converting to String
I am then displaying that in a UITextField
however I want to colour specific words. Ideally the user would type "LineBreak" and it would automatically change the word LineBreak to a different colour
It is my understanding this will need to use NSMutableAttributedString
however I don't know how to go about doing this
let string = "Test Specific Colour LineBreak TestLine2"
let attributedString = NSMutableAttributedString.init(string: string)
let range = (string as NSString).range(of: "LineBreak")
attributedString.addAttribute(NSAttributedString.Key.foregroundColor,
value: UIColor.blue, range: range)
txtView.attributedText = attributedString
So using the example above, I want to have the colour of "LineBreak" change whenever it is typed. The above works to change the colour but not every time I type it. I need to recognise that the string "LineBreak" is present and change its colour
What is the best way to achieve what I'm after?
Here's one approach to get you started...
Make sure your controller conforms to UITextViewDelegate
and you've assigned the text view's delegate:
class ExampleViewController: UIViewController, UITextViewDelegate {
@IBOutlet var theTextView: UITextView!
override func viewDidLoad() {
super.viewDidLoad()
theTextView.delegate = self
theTextView.text = "Test Specific Colour LineBreak TestLine2 linebreak and another LineBreak occurance"
formatTextInTextView(theTextView)
}
func textViewDidChange(_ textView: UITextView) {
formatTextInTextView(textView)
}
func formatTextInTextView(_ textView: UITextView) -> Void {
guard let curText = textView.text else { return }
let bScroll = textView.isScrollEnabled
textView.isScrollEnabled = false
let selRange = textView.selectedRange
let attributedString = NSMutableAttributedString.init(string: curText)
let regex = try! NSRegularExpression(pattern: "LineBreak", options: [.caseInsensitive])
let items = regex.matches(in: curText, options: [], range: NSRange(location: 0, length: curText.count))
let ranges: [NSRange] = items.map{$0.range}
for r in ranges {
attributedString.addAttribute(.foregroundColor, value: UIColor.red, range: r)
}
textView.attributedText = attributedString
textView.selectedRange = selRange
textView.isScrollEnabled = bScroll
}
}
You may want to limit it to case-sensitive, whole-word, etc...