如何在AttributedString中用正则匹配所有范围并设置属性?
解决AttributedString正则全匹配及属性设置问题
1. 获取所有匹配范围的正确方式
range(of:options:)确实只能返回第一个匹配项,要拿到所有符合<test>(.*?)</test>的范围,得用NSRegularExpression的全匹配能力。具体实现如下:
首先要把传入的AttributedString改为可变类型(原函数参数是不可变的let,无法修改属性),接着通过正则表达式找出所有匹配结果,再将每个结果的NSRange转换为AttributedString可识别的Range:
func testFunc(var attribString: AttributedString) -> AttributedString { // 示例输入:"Lorem ipsum dolor <test>first tag</test>sit Donec <test>second tag</test>" guard let regex = try? NSRegularExpression(pattern: "<test>(.*?)</test>") else { return attribString } // 转换为NSString适配NSRegularExpression的范围处理 let nsString = NSString(string: String(attribString)) let fullRange = NSRange(location: 0, length: nsString.length) // 获取所有匹配结果 let matches = regex.matches(in: String(attribString), options: [], range: fullRange) // 遍历匹配结果,设置对应范围的属性 for match in matches { let nsRange = match.range if let range = Range(nsRange, in: attribString) { attribString[range].foregroundColor = .red } } return attribString }
2. 循环遍历设置属性的可行性
你提出的for range in ranges { attribString[range].foregroundColor = .red }方案完全可行,但要注意两个关键点:
- 必须先一次性获取所有匹配范围,再遍历设置。虽然这里只是修改属性而非字符内容,但先拿到所有范围再处理能避免潜在的范围偏移问题。
- 传入的
attribString必须是可变的(var),原函数的不可变参数会导致修改属性时报错,必须调整参数类型。
额外提醒:如果你的AttributedString是Markdown解析后的结果,要确保正则匹配的是原始带标签的文本——如果Markdown已被解析为无标签的富文本,正则将无法匹配,此时需要在Markdown解析阶段就处理标签对应的样式。
内容的提问来源于stack exchange,提问作者Stefano Vet
相关产品推荐
相关产品推荐

