1
func testFunc(attribString: AttributedString)->AttributedString {

    // attribString is a markdown AttributedString for example = "Lorem ipsum dolor <test>first tag</test>sit Donec <test>second tag</test>"

    if let range = attribString.range(of: "<test>(.*?)</test>", options: .regularExpression) {

        attribString[range].foregroundColor = .red
        
    }
}

the documentation says: range(of) - Finds and returns the range of the first occurrence of a given string within the string.

But how can I find the range of all occurrences in the string with regex so that I can assign it a color or other attribute?

Could a loop be a good idea?

for range in ranges {
     attribString[range].foregroundColor = .red
}

Thanks for help

7
  • You can use a NSRegularExpression. Also, you don't remove the tag <test> & </test> afterwards? Commented Jul 27, 2022 at 20:26
  • for use NSRegularExpression and than enumerateMatches i need a string ... regex.enumerateMatches(in: attribString .... but attribString is an AttributeString ... thanks Commented Jul 27, 2022 at 20:53
  • Indeed. You could use NSAttributedString (since you can go NSAttributedString <-> AttributedString), and do it on that NSMutableAttributedString (mutable, since you modify it). Commented Jul 27, 2022 at 20:59
  • Or use a while/recursive loop: If you find a range, add the effect, then, break the AttributedString, from end of found range to end of it, and redo the range(of:options:) on the rest, etc. Commented Jul 27, 2022 at 21:00
  • have a look at this SO post "...To find all substrings that are between a starting string and an ending string." :stackoverflow.com/questions/31725424/… look for sliceMultipleTimes Commented Jul 27, 2022 at 23:10

1 Answer 1

1

here is a possible solution to achieve ...to keep the <test> </test> tags and color the whole block red... (adjust the code according to your needs). It does not involve regex, it is based on the code (sliceMultipleTimes) at: Swift Get string between 2 strings in a string

struct ContentView: View {
    @State var attStr: AttributedString?
    
    var body: some View {
        Text(attStr ?? "nothing")
            .onAppear {
                let str = "Lorem ipsum dolor <test>first tag</test> sit Donec <test>second tag</test>"
                attStr = transform(str, from: "<test>", to: "</test>", with: .red)
            }
    }

    func transform(_ input: String, from: String, to: String, with color: Color) -> AttributedString {
        var attInput = AttributedString(input)
        let _ = input.components(separatedBy: from).compactMap { sub in
            (sub.range(of: to)?.lowerBound).flatMap { endRange in
                let s = String(sub[sub.startIndex ..< endRange])
                // use `s` for just the middle string
                if let theRange = attInput.range(of: (from + s + to)) {
                    attInput[theRange].foregroundColor = color
                }
            }
        }
        return attInput
    }
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.