我有以下功能可以在 UILabel
中查找并突出显示主题标签或提及(@ 或 #):
class func addLinkAttribute(pattern: String,
toText text: String,
withAttributeName attributeName : String,
toAttributedString attributedString :NSMutableAttributedString,
withLinkAttributes linkAttributes: [NSObject : AnyObject]) {
var error: NSError?
if let regex = NSRegularExpression(pattern: pattern, options:.CaseInsensitive, error: &error) {
regex.enumerateMatchesInString(text, options: .allZeros, range: NSMakeRange(0, count(text))) { result, flags, stop in
let range = result.range
let start = advance(text.startIndex, range.location)
let end = advance(start, range.length)
let foundText = text.substringWithRange(Range<String.Index>(start: start,end: end))
var linkAttributesWithName = linkAttributes
linkAttributesWithName[attributeName] = foundText
attributedString.addAttributes(linkAttributesWithName, range: range)
}
}
}
如果我传递主题标签 (#)(\\w+)
或提及 (@)(\\w+)
模式,代码将完美运行,但如果文本包含一个表情符号的范围被它前面的表情符号的数量所抵消:
我知道 Swift 对待字符串的方式与 Objective-C 不同,因为 count(string)
和 count(string.utf16)
给我不同的结果,但我很困惑使用正则表达式时如何考虑这一点。
我可以只检查 2 个计数之间的差异并抵消范围,但这对我来说似乎是错误和 hacky 的。必须有另一种方法。
最佳答案
类似于Swift extract regex matches ,一个可能的解决方案是转换给定的 Swift String
到NSString
并申请 NSRange
返回者
enumerateMatchesInString()
那个NSString
:
class func addLinkAttribute(pattern: String,
toText text: String,
withAttributeName attributeName : String,
toAttributedString attributedString :NSMutableAttributedString,
withLinkAttributes linkAttributes: [NSObject : AnyObject]) {
let nsText = text as NSString
var error: NSError?
if let regex = NSRegularExpression(pattern: pattern, options:.CaseInsensitive, error: &error) {
regex.enumerateMatchesInString(text, options: .allZeros, range: NSMakeRange(0, nsText.length)) {
result, _, _ in
let range = result.range
let foundText = nsText.substringWithRange(range)
var linkAttributesWithName = linkAttributes
linkAttributesWithName[attributeName] = foundText
attributedString.addAttributes(linkAttributesWithName, range: range)
}
}
}
(替代解决方案。) 可以将 NSRange
转换为至 Range<String.Index>
无需中间转换为 NSString
.
与
extension String {
func rangeFromNSRange(nsRange : NSRange) -> Range<String.Index>? {
let utf16start = self.utf16.startIndex
if let from = String.Index(self.utf16.startIndex + nsRange.location, within: self),
let to = String.Index(self.utf16.startIndex + nsRange.location + nsRange.length, within: self) {
return from ..< to
}
return nil
}
}
来自 https://stackoverflow.com/a/30404532/1187415 ,你的代码可以是 写成
class func addLinkAttribute(pattern: String,
toText text: String,
withAttributeName attributeName : String,
toAttributedString attributedString :NSMutableAttributedString,
withLinkAttributes linkAttributes: [NSObject : AnyObject]) {
var error: NSError?
if let regex = NSRegularExpression(pattern: pattern, options:.CaseInsensitive, error: &error) {
regex.enumerateMatchesInString(text, options: .allZeros, range: NSMakeRange(0, count(text.utf16))) {
result, _, _ in
let nsRange = result.range
if let strRange = text.rangeFromNSRange(nsRange) {
let foundText = text.substringWithRange(strRange)
var linkAttributesWithName = linkAttributes
linkAttributesWithName[attributeName] = foundText
attributedString.addAttributes(linkAttributesWithName, range: nsRange)
}
}
}
}
这也应该适用于各种扩展字素 集群(表情符号、区域指标等...)
关于ios - 如何在 Swift 中突出显示包含表情符号的字符串中的文本?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30400969/