Swift 中的String
在過去幾年時間里面學(xué)習(xí)了好幾門語言,他們分別是:
- Swift1.0
- Swift2.0
- Swift3.0
- Swift4.0
- Swift5.0
好了 現(xiàn)在終于不用學(xué)那么多了,又來一個SwiftUI
在這么多語言中 String變了好幾回,每次用的時候都要去現(xiàn)查,現(xiàn)在是怎么使用的。很煩人,現(xiàn)在來研究一下為什么一直在變,為什么不用int 類型下標(biāo)、還有一堆亂七八糟的問題。
1. 為什么不用int 類型下標(biāo)
String 使用UTF-8編碼,每個字符由1 - 4個UTF - 8編碼單位組成,所以字符串的長度就不是固定,所以如果使用 int 下標(biāo)要先遍歷字符串獲取長度。
# 假設(shè) String 以 Int 為 index
let hello = "hello"
for i in 0...hello.count{
print(hello[i])
}
# 時間復(fù)雜度為 O(n^2)
# O(1) + O(2) + O(3) + ... + O(n) = O(n!) ≈ O(n^2)
由此進(jìn)行改進(jìn):
使用偏移量來迭代
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)
}
// 時間復(fù)雜度為 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不是規(guī)律的,偏移量每次都不一樣
所以引出了下一個問題
2. 為什么都要用實(shí)例方法
同一個字符串每個字符之間的偏移都不同,那么不同字符串呢,比如:我用字符串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 再大一點(diǎn)(比如調(diào)整成 5 )就報錯了
Fatal error: String index is out of bounds: file Swift/StringRangeReplaceableCollection.swift, line 302
3. 為什么要支持不等長的元素,和其他語言一樣不好嗎?
如果collection 不支持不等長的元素和其他語言一樣,那就非常簡單了,String這種類型單獨(dú)處理一下就好了。
swift1.0 時 String 遵循 Collection 協(xié)議
swift2 - 3 時 移除了這個 conformance
swift 4 又改回去了。 真是日了狗!!
狗頭
Swift 更傾向于 API 的正確性,而不是易用性,所以 全部上Index