0

I have a UITextView in which I would like to add a background to the text (hightlight it). I want everything but new lines to be highlighted. How can I achieve this?

4
  • NSAttributedString or UITextView selectedRange, depending on what you really want? Commented Jan 6, 2022 at 13:19
  • Well I'm pretty sure I need the backgroundColor of the NSAttributedString but I'm not sure on how to parse and find lines that are just empty new lines and not apply the backgroundColor on them. Commented Jan 6, 2022 at 13:26
  • With NSAttributedString, I'm not sure if empty lines would have the background. Did you checked beforehand? Commented Jan 6, 2022 at 13:26
  • Yes, it unfortunately adds the background to newlines too. Commented Jan 6, 2022 at 13:32

1 Answer 1

1

You can enumerate (enumerate(_:in:option:)) on the NSAttributedString.Key.backgroundColor to find change only when it has a background. Then, you can use a regex, or a while loop with range(of:) to find where they are, and remove the .backgroundColor on them:

With sample code on Playgrounds:

func highlights() -> UITextView { let tv = UITextView(frame: CGRect(x: 0, y: 0, width: 300, height: 200)) tv.backgroundColor = .orange let text = "Hello world! How are you today?\nLet's start do some testing.\nAnd this is a long paragraph just to see it to the end of the line." let attributes: [NSAttributedString.Key: Any] = [.font: UIFont.boldSystemFont(ofSize: 15.0), .backgroundColor: UIColor.systemPink] let first = NSAttributedString(string: text, attributes: attributes) let second = NSMutableAttributedString(string: text, attributes: attributes) guard let regex = try? NSRegularExpression(pattern: "\n", options: []) else { return tv } second.enumerateAttribute(.backgroundColor, in: NSRange(location: 0, length: second.length), options: []) { attribute, range, stop in guard attribute as? UIColor != nil else { return } guard let subrange = Range(range, in: second.string) else { return } let substring = String(second.string[subrange]) let ranges = regex.matches(in: substring, options: [], range: NSRange(location: 0, length: substring.utf16.count)) ranges.forEach { second.removeAttribute(.backgroundColor, range: $0.range) } } let total = NSMutableAttributedString() total.append(first) total.append(NSAttributedString(string: "\nNormal Text, nothing to see here\n")) total.append(second) total.append(NSAttributedString(string: "\nNormal Text, nothing to see here\n")) tv.attributedText = total return tv } let tv = highlights() 

enter image description here

Side note: I didn't handle the case if you have in the string "\n \n", that might need some changes in the regex pattern. After a quick test, then NSRegularExpression(pattern: "\n(\\s+\n)*", options: []) might do the trick.

Sign up to request clarification or add additional context in comments.

1 Comment

Works like a charm, thanks! :)

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.