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
有兴趣的其实可以打印一下这个