更好的 API 命名
初始化一个 String
标准库把 String
的初始化方法 init(count: repeatedValue:)
改成了 init(repeating: count:)
, repeatedValue
的类型也从 Character
字符换成了 String
字符串去获得更多灵活性:
// Swift 2
let h = String(count:3, repeatedValue:"0") // "000"
// Swift 3
let h = String(repeating:"01", count:3) // 010101
大小写转换
uppercaseString
和 lowercaseString
两个属性现在变成了函数, 重新命名为 uppercased()
和 lowercased()
:
let mixedCase = "AbcDef"
// Swift 2
// let upper = mixedCase.uppercaseString // "ABCDEF"
// let lower = mixedCase.lowercaseString // "abcdef"
// Swift 3
let upper = mixedCase.uppercased() // "ABCDEF"
let lower = mixedCase.lowercased() // "abcdef"
接下来我还会讲到一些别的命名的变化
使用索引去访问集合
let country = "España"
country.characters // characters
country.unicodeScalars // Unicode scalar 21-bit codes
country.utf16 // UTF-16 encoding
country.utf8 // UTF-8 encoding
Swift 3里每个集合的 view 里的 startIndex
和 endIndex
属性还是没变:
let hello = "hello"
let helloStartIndex = hello.characters.startIndex // 0
如果想要获取字符的集合, 你也可以使用 characters
属性:
(译者注: characters
能够自动帮助我们处理编码问题, 让我们获得人类理解的"字符集合". Swift 的字符串 API 刚接触可能会觉得很难用, 但了解了背后的原理之后, 会发现它其实做了很多, 帮我们避开了很多坑, 了解方法之后也很容易使用)
let startIndex = hello.startIndex // 0
let endIndex = hello.endIndex // 5
hello[startIndex] // "h"
之前通过增减索引去访问字符串的方式改变了, successor()
, predecessor()
和 advancedBy(n)
的函数都去掉了.
// Swift 2
hello[hello.startIndex] // "h"
hello[hello.startIndex.successor()] // "e"
hello[hello.endIndex.predecessor()] // "o"
hello[hello.startIndex.advancedBy(2)] // "l"
现在在 Swift 3 里你会使用 index(after:)
, index(before:)
和 index(_: offsetBy:)
去处理相同的情况:
// Swift 3
hello[hello.startIndex] // "h"
hello[hello.index(after: startIndex)] // "e"
hello[hello.index(before: endIndex)] // "o"
hello[hello.index(startIndex, offsetBy: 1)] // "e"
hello[hello.index(endIndex, offsetBy: -4)] // "e"
你也可以给 offset 加上限制, 避免错误的下标访问. 函数 index(_: offsetBy: limitedBy:)
会返回一个可选值, 下标越界的时候就会返回 nil
:
if let someIndex = hello.index(startIndex,
offsetBy: 4, limitedBy: endIndex) {
hello[someIndex] // "o"
}
找到第一个符合条件的元素<T>的方式(在这种情况下, T 是一个字符串):
let matchedIndex = hello.characters.index(of: "l") // 2
let nomatchIndex = hello.characters.index(of: "A") // nil
最后, 获取两个索引之间距离的方法现在也被重新命名了:
// Swift 2
let distance = word1.startIndex.distanceTo(indexC)
// Swift 3
let distance = word1.distance(from: word1.startIndex, to: indexC)
使用 Ranges (范围)
Swift 3 里对 Ranges 进行了修改. 假设我有字符集合的一个起始索引值和一个终点索引值:
let fqdn =
let tldEndIndex = fqdn.endIndex
let tldStartIndex = fqdn.index(tldEndIndex, offsetBy: -3)
用起始和终点索引去初始化 Range 的方式:
let range = Range(uncheckedBounds: (lower: tldStartIndex, upper: tldEndIndex))
fqdn[range] // "com"
创建一个范围最简单的方法就是使用 ..<
和 ...
操作符:
let endOfDomain = fqdn.index(fqdn.endIndex, offsetBy: -4)
let rangeOfDomain = fqdn.startIndex ..< endOfDomain
fqdn[rangeOfDomain] // useyourloaf
查找和返回子字符串的范围:
if let rangeOfTLD = fqdn.range(of: "com") {
let tld = fqdn[rangeOfTLD] // "com"
}