用属性字符串和文本替换正则表达式匹配

Replace regex match with attributed string and text

我们的应用程序 Api returns 具有自定义格式的字段,用于 用户提及 就像: "this is a text with mention for @(steve|user_id)"。 所以在 UITextView 上显示它之前,需要处理文本,找到模式并替换为更用户友好的内容。 最终结果将是 "this is a text with mention for @steve",其中 @steve 应该有一个 link 属性和 user_id。基本与 Facebook 功能相同。

首先,我创建了一个 UITextView 扩展,具有正则表达式模式的匹配功能。

extension UITextView {
    func processText(pattern: String) {
        let inString = self.text
        let regex = try? NSRegularExpression(pattern: pattern, options: [])
        let range = NSMakeRange(0, inString.characters.count)
        let matches = (regex?.matchesInString(inString, options: [], range: range))! as [NSTextCheckingResult]

        let attrString = NSMutableAttributedString(string: inString, attributes:attrs)

        //Iterate over regex matches
        for match in matches {
            //Properly print match range
            print(match.range)

           //A basic idea to add a link attribute on regex match range
            attrString.addAttribute(NSLinkAttributeName, value: "\(schemeMap["@"]):\(must_be_user_id)", range: match.range)

           //Still text it's in format @(steve|user_id) how could replace it by @steve keeping the link attribute ?
        }
    }
}

//To use it
let regex = ""\@\(([\w\s?]*)\|([a-zA-Z0-9]{24})\)""
myTextView.processText(regex)

这就是我现在拥有的,但我一直在尝试获得最终结果

非常感谢!

我稍微修改了你的正则表达式,但得到了很好的结果。也稍微修改了代码,可以直接在Playgrounds中测试。

func processText() -> NSAttributedString {
    let pattern = "(@\(([^|]*)([^@]*)\))"
    let inString = "this is a text with mention for @(steve|user_id1) and @(alan|user_id2)."
    let regex = try? NSRegularExpression(pattern: pattern, options: [])
    let range = NSMakeRange(0, inString.characters.count)
    let matches = (regex?.matchesInString(inString, options: [], range: range))!

    let attrString = NSMutableAttributedString(string: inString, attributes:nil)
    print(matches.count)
    //Iterate over regex matches
    for match in matches.reverse() {
        //Properly print match range
        print(match.range)

        //Get username and userid
        let userName = attrString.attributedSubstringFromRange(match.rangeAtIndex(2)).string
        let userId = attrString.attributedSubstringFromRange(match.rangeAtIndex(3)).string

        //A basic idea to add a link attribute on regex match range
        attrString.addAttribute(NSLinkAttributeName, value: "\(userId)", range: match.rangeAtIndex(1))

        //Still text it's in format @(steve|user_id) how could replace it by @steve keeping the link attribute ?
        attrString.replaceCharactersInRange(match.rangeAtIndex(1), withString: "@\(userName)")
    }
    return attrString
}