Swift 中的String
在过去几年时间里面学习了好几门语言,他们分别是:
- Swift1.0
- Swift2.0
- Swift3.0
- Swift4.0
- Swift5.0
好了 现在终于不用学那么多了,又来一个SwiftUI
在这么多语言中 String变了好几回,每次用的时候都要去现查,现在是怎么使用的。很烦人,现在来研究一下为什么一直在变,为什么不用int 类型下标、还有一堆乱七八糟的问题。
1. 为什么不用int 类型下标
String 使用UTF-8编码,每个字符由1 - 4个UTF - 8编码单位组成,所以字符串的长度就不是固定,所以如果使用 int 下标要先遍历字符串获取长度。
# 假设 String 以 Int 为 index
let hello = "hello"
for i in 0...hello.count{
print(hello[i])
}
# 时间复杂度为 O(n^2)
# O(1) + O(2) + O(3) + ... + O(n) = O(n!) ≈ O(n^2)
由此进行改进:
使用偏移量来迭代
let hello = "hello"
/// String.Index 类型
var index = hello.startIndex
while index != hello.endIndex{
print(hello[index])
print(hello.index(after: index))
index = hello.index(after: index)
}
// 时间复杂度为 O(n)
// O(1) + O(1) + O(1) + ... + O(1) = O(n)
Index(_rawBits: 65793)
Index(_rawBits: 131329)
Index(_rawBits: 196865)
Index(_rawBits: 262401)
Index(_rawBits: 327681)
但是我们可以看到index不是规律的,偏移量每次都不一样
所以引出了下一个问题
2. 为什么都要用实例方法
同一个字符串每个字符之间的偏移都不同,那么不同字符串呢,比如:我用字符串A的偏移量,来迭代字符串B会有什么情况
let strA = "垃圾Swift"
// 从开始便宜两个单位
let index = strA.index(strA.startIndex, offsetBy: 2)
print(strA[index])
> S
let strB = "Object-c"
print(strB[index])
> -
使用同一个index在不同字符串之间,取到的字符不是我们想要的 j
要是我offset 再大一点(比如调整成 5 )就报错了
Fatal error: String index is out of bounds: file Swift/StringRangeReplaceableCollection.swift, line 302
3. 为什么要支持不等长的元素,和其他语言一样不好吗?
如果collection 不支持不等长的元素和其他语言一样,那就非常简单了,String这种类型单独处理一下就好了。
swift1.0 时 String 遵循 Collection 协议
swift2 - 3 时 移除了这个 conformance
swift 4 又改回去了。 真是日了狗!!Swift 更倾向于 API 的正确性,而不是易用性,所以 全部上Index