![在此输入图片描述](https://istack.dev59.com/GrSxA.webp)
以下所有示例均使用:
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)
示例
let index = str.index(after: str.startIndex)
str[index]
let range = str.index(after: str.startIndex)..<str.endIndex
str[range]
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
。
示例
let index = str.index(str.startIndex, offsetBy: 7)
str[index]
let start = str.index(str.startIndex, offsetBy: 7)
let end = str.index(str.endIndex, offsetBy: -6)
let range = start..<end
str[range]
limitedBy
例如: index(String.Index, offsetBy: String.IndexDistance, limitedBy: String.Index)
limitedBy
用于确保偏移量不会导致索引越界。它是一个限制性索引。由于偏移量可能超过限制,因此该方法返回一个Optional。如果索引越界,则返回nil
。
例子:
if let index = str.index(str.startIndex, offsetBy: 7, limitedBy: str.endIndex) {
str[index]
}
如果偏移量是
77
而不是
7
,那么
if
语句会被跳过。
为什么需要String.Index?
对于字符串来说,使用一个Int
类型的索引会更容易。但Swift中的字符在底层并不都是相同的长度。一个单独的Swift字符可能由一个、两个甚至更多的Unicode码点组成。因此,每个唯一的字符串必须计算其字符的索引。
可以通过Int类型的索引扩展来隐藏这种复杂性,但我不愿意这样做。了解实际发生的事情是很好的。
startIndex
会是除了0以外的其他值? - Robo Roboké
,它实际上由e
和\u{301}
的Unicode表示组成。如果你使用索引0,你将得到e
或重音符号(“grave”)字符之一,而不是组成é
的整个簇。使用startIndex
可以确保您获得任何字符的完整字形簇。 - leanne.index
方法之外,如何从整数构造String.Index
?我不知道是否有遗漏什么,但文档中没有说明。 - sudoString.Index
时,你需要小心,因为每个Swift的Character
都不一定等于你用一个整数所表示的意思。尽管如此,你可以将整数传入offsetBy
参数来创建一个String.Index
。但是如果你没有一个字符串,则无法构造一个String.Index
(因为Swift只有在了解字符串中前面的字符后才能计算索引)。如果你改变了字符串,那么你必须重新计算索引。你不能在两个不同的字符串上使用相同的String.Index
。 - Suragch