Swift5中String.count 与 NSString.length不相等

本文探讨了Swift5中String.count与NSString.length的区别,特别是在处理包含emoji的表情字符串时出现的问题。通过调整使用str.utf16.count解决了匹配不一致的情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Swift5中String.count 与 NSString.length不相等

问题描述

  • 在我对微博国际版的Text显示框架进行重构的时候,发现了会有部分在末尾的文字内容无法解析成对应的样式。

梳理后发现了这样的问题:

    let topicRegex: NSRegularExpression? = try? NSRegularExpression(pattern: "#[^#']+#", options: .caseInsensitive)
    let str = "文本文本文本文本文本🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂文本文本文本#话题1##话题2##话题3##话题4##话题5##话题6##话题7##话题8##话题9#"
    func topicRegexHasEmojTest() {
        if let results = topicRegex?.matches(in: str, options: [], range: NSRange(location: 0, length: str.count)) {
            var resultStrs = ""
            for result in results {
                resultStrs.append(NSString(string: str).substring(with: result.range))
            }
            print("1:"+resultStrs)
            print("----------")
        }
    }

代码打印结果为:
1:#话题1##话题2##话题3##话题4##话题5##话题6#
而最末尾的#话题7##话题8##话题9#没有被成功解析,如果把文本中的emoj🎂删除,则有可以搜索到所有字符,这里我意识到,可能是正则寻找的count出现了问题。

  • 于是我做了下面的测试:
let str1 = "❤️❤️🎂🎂"
let str2 = NSString(string: str1)
print("str1.count = \(str1.count), str2.length = \(str2.length)")
//str1.count = 4, str2.length = 8

  • 实锤了,swift.count跟NSString.length的确不是一个玩意,尤其在emoj上,一个emoj表情占的明显比一个汉字要多。
  • 问题发现了,但是解决时候其实有点困难,因为在网上没有搜索到明显关于这方面的解答。不过运气不错的是,我在看Swift的String注释文档时候,看到了这样的内容:
/// The UTF-16 code units of a string's `utf16` view match the elements
     /// accessed through indexed `NSString` APIs.
     ///
     ///     print(flowers.utf16.count)
     ///     // Prints "10"
     ///
     ///     let nsflowers = flowers as NSString
     ///     print(nsflowers.length)
     ///     // Prints "10"
     ///
     /// Unlike `NSString`, however, `String.UTF16View` does not use integer
     /// indices. If you need to access a specific position in a UTF-16 view, use
     /// Swift's index manipulation methods. The following example accesses the
     /// fourth code unit in both the `flowers` and `nsflowers` strings:
  • 所以就是说,swift中String如果用str.utf16.count 那么就可以等于NSString.length吧,说没用,试试:
let str1 = "❤️❤️🎂🎂"
let str2 = NSString(string: str1)
print("str1.count = \(str1.count), str1.utf16.count = \(str1.utf16.count), str2.length = \(str2.length)")
str1.count = 4, str1.utf16.count = 8, str2.length = 8

问题解决

当我用str.utf16.count 时候,就可以得到和NSString一样的长度了。

    func topicRegexHas2EmojTest() {
        if let results = topicRegex?.matches(in: str, options: [], range: NSRange(location: 0, length: str.utf16.count)) {
            var resultStrs = ""
            for result in results {
                resultStrs.append(NSString(string: str).substring(with: result.range))
            }
            print("2:"+resultStrs)
            print("----------")
        }
    }

//2:#话题1##话题2##话题3##话题4##话题5##话题6##话题7##话题8##话题9#
//----------

ps

有兴趣的其实可以打印一下这个👩‍👩‍👧‍👦

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值