以下所有示例都使用
var str = "Hello, playground"
startIndex 和 endIndex
-
startIndex 是第一个字符的索引
-
endIndex 是在最后一个字符之后的索引。
例子
// character
str[str.startIndex] // H
str[str.endIndex] // error: after last character
// range
let range = str.startIndex..<str.endIndex
str[range] // "Hello, playground"
使用 Swift 4 的 one-sided ranges,范围可以简化为以下形式之一。
let range = str.startIndex...
let range = ..<str.endIndex
为了清楚起见,我将在以下示例中使用完整形式,但为了便于阅读,您可能希望在代码中使用单边范围。
after
如:index(after: String.Index)
例子
// character
let index = str.index(after: str.startIndex)
str[index] // "e"
// range
let range = str.index(after: str.startIndex)..<str.endIndex
str[range] // "ello, playground"
before
如:index(before: String.Index)
例子
// character
let index = str.index(before: str.endIndex)
str[index] // d
// range
let range = str.startIndex..<str.index(before: str.endIndex)
str[range] // Hello, playgroun
offsetBy
如:index(String.Index, offsetBy: String.IndexDistance)
-
offsetBy 值可以是正数或负数,并且从给定索引开始。虽然它是String.IndexDistance 类型,但您可以给它一个Int。
例子
// character
let index = str.index(str.startIndex, offsetBy: 7)
str[index] // p
// range
let start = str.index(str.startIndex, offsetBy: 7)
let end = str.index(str.endIndex, offsetBy: -6)
let range = start..<end
str[range] // play
limitedBy
如:index(String.Index, offsetBy: String.IndexDistance, limitedBy: String.Index)
-
limitedBy 可用于确保偏移不会导致索引超出范围。它是一个边界索引。由于偏移量可能超出限制,因此此方法返回一个 Optional。如果索引超出范围,则返回 nil。
例子
// character
if let index = str.index(str.startIndex, offsetBy: 7, limitedBy: str.endIndex) {
str[index] // p
}
如果偏移量是77 而不是7,则将跳过if 语句。
为什么需要 String.Index?
对字符串使用Int 索引会更容易很多。您必须为每个字符串创建一个新的String.Index 的原因是 Swift 中的字符在引擎盖下的长度并不完全相同。单个 Swift 字符可能由一个、两个甚至更多的 Unicode 代码点组成。因此,每个唯一的字符串都必须计算其字符的索引。
可以将这种复杂性隐藏在 Int 索引扩展后面,但我不愿意这样做。提醒一下实际发生的事情是件好事。