以下所有示例均使用
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的单边范围,范围可以简化为以下形式之一。
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
}
如果使用offset 77
代替7
,则该if
语句将被跳过。
为什么需要String.Index?
对字符串使用索引会容易得多Int
。您必须String.Index
为每个String 创建一个新字符串的原因是,Swift中的Characters在引擎盖下的长度并不相同。一个Swift字符可能由一个,两个甚至更多个Unicode代码点组成。因此,每个唯一的String必须计算其Characters的索引。
可能会将这种复杂性隐藏在Int索引扩展的后面,但是我不愿意这样做。最好提醒一下实际发生的事情。
startIndex
除0以外的其他值?