这儿每天共享一个 iOS 的新知识,快来关注我吧

前语

字符串是 swift 中的一个十分基础的类型,我们平常运用最多的想必也是这个类型了,但是有一些底层完成和躲藏能力,许多人还不知道,今天就来聊聊这块内容。

长度问题

不知道我们平常开发时有没有注意过,swift 中的 String 和 NSString 是能够用 as 无缝转化的,但是 String 的 count 特点和 NSString 的 length 的值或许不同。

比如:

let swiftString = " ‍ ‍ ‍ "
let nsString = swiftString as NSString
print(swiftString.count) // 打印 1
print(nsString.length) // 打印 11

同样是一个 emoji 符号,swift String 的 count 打印 1,但是转成 NSString 运用 length 打印 11。

这是因为,count 特点是测量的屏幕上显示的字符数,这儿的 emoji 在屏幕上只显示一个字符,所以值是 1。

而 NSString 是运用 UTF-16 编码的,它的 length 特点实际上是 UTF-16 编码的长度。这在 NSString 的文档上有标示:

关于 swift 中的字符串,你或许还不知道的工作

swift 的字符串也能够转成 UTF-16 编码,这样,打印的 count 也是 11 了:

let swiftString = " ‍ ‍ ‍ "
print(swiftString.utf16.count) // 打印 11

关于 Unicode 编码

前面提到了 Unicode 编码,许多程序员都搞不明白,这儿顺带提一句,Unicode 是一种计算机文本编码规范,简单来说便是让字符显示在屏幕上的。

在 Unicode 编码呈现之前,世界上还有许多编码规范,比如 ASCII、ISO 8859-1 等,编码方式不一致,解码的时分就会呈现乱码的状况,后来就规划了 Unicode 编码,我们用同一套规范,这样就不会乱码了。

上边提到的 UTF-16 其实是 Unicode 的一种编码方案,为了在内存运用、兼容性和编码效率之间获得平衡,Unicode 规范界说了 UTF-8、UTF-16、UTF-32 几种不同的编码方案,iOS 内部运用的便是 UTF-16。

其实 swift 提供了几种编码的转化函数,能够自在切换:

let swiftString = " ‍ ‍ ‍ "
print(swiftString.utf8.count) // utf8 打印 25
print(swiftString.utf16.count) // utf16 打印 11
print(swiftString.unicodeScalars.count) // utf32 打印 7

查看字符串

之前看到一些开源项目在判断空字符串时运用 string.count == 0,每逢看到这样的写法,我都会顺手提个 PR 改成 string.isEmpty

相比之下,用 string.isEmpty 来判断空字符串的功能更好,因为在底层完成中 count 特点需求遍历字符串的元素。

系统对字符串的功能优化

写入时仿制(Copy-on-Write)

我们都知道 Swift 的字符串是值类型的,这意味着每个字符串变量都拥有独立的数据副本。本来每次读写都会发生一份新的副本,但这会发生较高的功能开支。

为了削减功能开支,Swift 引入了一种称为“写入时仿制”(Copy-on-Write, COW)的战略来优化这一过程。

具体来说,当你仿制一个字符串时,Swift 并不当即仿制字符串的数据,而是让新旧字符串实例共享相同的的数据缓冲区。只有当你测验修正其中一个字符串时,Swift 才会进行实际的数据仿制操作。也便是在只有真正需求时才会发生数据的仿制,然后削减了不必要的功能开支。

这种机制带来一个结果,假如你有多个字符串实例共享同一个数据缓冲区,那么对其中一个字符串进行修正的操作或许会导致 O(n) 的时刻和空间开支,因为需求仿制整个数据缓冲区。这儿的 n 指的是字符串的长度。

缓冲区的指数增加战略

Swift 的字符串还采用了一种缓冲区的指数增加战略来优化字符串的追加操作。当你向字符串追加内容时,假如当时的数据缓冲区已满,Swift 会分配一个新的更大的缓冲区,并将现有数据仿制到这个新缓冲区中。

这个新缓冲区的巨细并不是简单地加上新增数据的巨细,而是依照一定的份额(通常是翻倍)增加,以便为未来的追加操作留出空间。这种战略的好处是,虽然某次特定的追加操作或许需求重新分配缓冲区并仿制数据(这是一次较为贵重的操作),但随着缓冲区巨细的增加,这种状况发生的频率会逐步削减。在对很多追加操作进行平均时,每次追加操作的平均时刻成本会趋近于常数(O(1)),然后提高了追加操作的整体功能。

关于 swift 中的字符串,你或许还不知道的工作

这儿每天共享一个 iOS 的新知识,快来关注我吧

本文同步自微信公众号 “iOS新知”,每天准时共享一个新知识,这儿只是同步,想要及时学到就来关注我吧!