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

Posted 翟乃玉

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Swift5中String.count 与 NSString.length不相等相关的知识,希望对你有一定的参考价值。

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

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

以上是关于Swift5中String.count 与 NSString.length不相等的主要内容,如果未能解决你的问题,请参考以下文章

猫猫学编码

猫猫学编码

cURL SSL连接错误35与NSS错误-5961

Curl 失败:NSS:未找到客户端证书(未指定昵称)-在 Centos 7 上

Swift5 新特性预览

在 Master (SPI) 中设置 nss_soft