3

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 !

1 Answer 1

7

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
}
Sign up to request clarification or add additional context in comments.

2 Comments

Mate but there is one issue, if you have 2 users, just apply NSLinkAttributeName to last one !
Sorry, didn't take it into account. Please, check my updated solution.

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.