Search code examples
swiftreplaceattributesnsattributedstringnsmutableattributedstring

Swift finding and changing range in attributed string


What would be the best way to change this string:

"gain quickness for 5 seconds. <c=@reminder>(Cooldown: 90s)</c> only after"

into an Attributed String while getting rid of the part in the <> and I want to change the font of (Cooldown: 90s). I know how to change and make NSMutableAttributedStrings but I am stuck on how to locate and change just the (Cooldown: 90s) in this case. The text in between the <c=@reminder> & </c> will change so I need to use those to find what I need.

These seem to be indicators meant to be used for this purpose I just don't know ho.


Solution

  • First things first, you'll need a regular expression to find and replace all tagged strings.

    Looking at the string, one possible regex could be <c=@([a-zA-Z-9]+)>([^<]*)</c>. Note that will will work only if the string between the tags doesn't contain the < character.

    Now that we have the regex, we only need to apply it on the input string:

    let str = "gain quickness for 5 seconds. <c=@reminder>(Cooldown: 90s)</c> only after"
    let attrStr = NSMutableAttributedString(string: str)
    let regex = try! NSRegularExpression(pattern: "<c=@([a-zA-Z-9]+)>([^<]*)</c>", options: [])
    while let match = regex.matches(in: attrStr.string, options: [], range: NSRange(location: 0, length: attrStr.string.utf16.count)).first {
        let indicator = str[Range(match.range(at: 1), in: str)!]
        let substr = str[Range(match.range(at: 2), in: str)!]
        let replacement = NSMutableAttributedString(string: String(substr))
        // now based on the indicator variable you might want to apply some transformations in the `substr` attributed string
        attrStr.replaceCharacters(in: match.range, with: replacement)
    }