Ad

Change Word Colour From Sentence With Regex

- 1 answer

I have sentence "This is my first test", I need to change for example word "first" to another colour. But this sentences will come from backend. So,i need maybe with regex take word from sentence, and back it with another colour. How to back this word into sentence, or maybe better way to change colour of word from sentence?

     var string = "This is my text=\"first\" test!"
        let pattern = ".*(?=( - text=\"[\\w\\s]+\"))|(?<=text=\")([\\w\\s]+)"

        do {
            let regex = try NSRegularExpression(pattern: pattern, options: .caseInsensitive)
            let matches = regex.matches(in: string, options: [], range: NSRange(location: 0, length: string.utf16.count))
            for match in matches {
                if let range = Range(match.range, in: string) {
                    let name = string[range]
                    if let range = string.range(of: "text=\"\(name)\"") {
                        string.removeSubrange(range)
                        debugPrint("WORD CHANGE COLOR: \(name)") // first
                        debugPrint("PHRASE IS: \(string)") // This is my test!
                    }
                    let attrs1 = [NSAttributedString.Key.font :  UIFont.systemFont(ofSize: 20), NSAttributedString.Key.foregroundColor : UIColor.green]
                    let attrs2 = [NSAttributedString.Key.font :  UIFont.systemFont(ofSize: 20), NSAttributedString.Key.foregroundColor : UIColor.black]
                    let attributedString1 = NSMutableAttributedString(string: String(name),attributes:attrs1)
                    let attributedString2 = NSMutableAttributedString(string: self.phrase, attributes: attrs2)
                    
                    titleLabel.attributedText = attributedString1
//                    titleLabel.attributedText = attributedString2
                }
            }
        } catch {
            print("Regex was bad!")
        }
Ad

Answer

Here's a working solution (with extra initial values to be usable in Playgrounds).

What's the idea:
Work directly on a NS(Mutable)AttributedString. Change the regex pattern, to let you know what's the real full range, what's the range of "first".
Enumerate the matches in reverse (because you'll be modifying the string, so the ranges won't be valid afterwards, since replacement won't have the same length)

let titleLabel = UILabel(frame: CGRect(x: 0, y: 0, width: 200, height: 100))
titleLabel.backgroundColor = .blue


let string = "This is my text=\"first\" test!"
let attributedString = NSMutableAttributedString(string: string, attributes: [NSAttributedString.Key.font :  UIFont.systemFont(ofSize: 20), NSAttributedString.Key.foregroundColor : UIColor.black])

let pattern = "text=\"([\\w\\s]+)\""

do {
    let regex = try NSRegularExpression(pattern: pattern, options: .caseInsensitive)
    let matches = regex.matches(in: attributedString.string, options: [], range: NSRange(location: 0, length: attributedString.length))

    for match in matches.reversed() {
        let globalNSRange = match.range
        let worldNSRange = match.range(at: 1)
        let replacement = NSMutableAttributedString(attributedString: attributedString.attributedSubstring(from: worldNSRange))
        replacement.addAttributes([NSAttributedString.Key.font :  UIFont.systemFont(ofSize: 20),
                                   NSAttributedString.Key.foregroundColor : UIColor.green],
                                  range: NSRange(location: 0, length: replacement.length))
        attributedString.replaceCharacters(in: globalNSRange, with: replacement)
    }

    titleLabel.attributedText = attributedString
} catch {
    print("Regex was bad: \(error)") //Print useful information on why it failed, like the actual thrown error
}

return titleLabel
Ad
source: stackoverflow.com
Ad