ios - 如何在 Swift 中突出显示包含表情符号的字符串中的文本?

标签 ios regex swift emoji

我有以下功能可以在 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+) 模式,代码将完美运行,但如果文本包含一个表情符号的范围被它前面的表情符号的数量所抵消:

enter image description here

我知道 Swift 对待字符串的方式与 Objective-C 不同,因为 count(string)count(string.utf16) 给我不同的结果,但我很困惑使用正则表达式时如何考虑这一点。

我可以只检查 2 个计数之间的差异并抵消范围,但这对我来说似乎是错误和 hacky 的。必须有另一种方法。

最佳答案

类似于Swift extract regex matches ,一个可能的解决方案是转换给定的 Swift StringNSString并申请 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/

相关文章:

iphone - 如果我本地化我的 iPhone 应用程序,(描述语言)但不更改我的应用程序,它会被拒绝吗?

javascript - 使用正则表达式匹配路径的中间?

swift - 使用 NSTreeController 过滤 NSOutlineView 的子级

ios - 如何将应用商店应用链接添加到应用内,而不是打开 "app store.app"?

ios - .request 调用中的额外参数——Alamofire + Swift

regex - 如何为一个原始模式搜索执行多个就地 SEDS?

iOS Swift 二维数组排序

ios - 在 Swift ARKit 中显示多行文本时,缓冲区会导致先前/过多的 GPU 错误

iphone - iOS 上 PhoneGap 2.0 的应用内购买 (IAP) 插件?

javascript - 如何比较路径是否在同一个文件夹中