Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Replace regex match with attributed string and text

Our app Api returns a field with custom format for user mentions just like: "this is a text with mention for @(steve|user_id)". So before display it on UITextView, need to process the text, find the pattern and replace with something more user friendly. Final result would be "this is a text with mention for @steve" where @steve should have a link attribute with user_id. Basically the same functionality as Facebook.

First I've created an UITextView extension, with a match function for the regex pattern.

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)

This is what I have right now, but I'm stucked trying to get final result

Thanks a lot !

like image 574
Steve Avatar asked Aug 10 '26 07:08

Steve


1 Answers

I changed your regex a bit, but got a pretty good result. Modified the code a little as well, so you can test it directly in 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
}
like image 146
konrad.bajtyngier Avatar answered Aug 12 '26 22:08

konrad.bajtyngier



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!