用属性字符串和文本替换正则表达式匹配
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
}
我们的应用程序 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
}