Swift 3 String.Index总结

最近工作中遇到很多字符串截取相关的内容,但Swift中字符串的截取开始时用着总是不如OC顺手,最近终于弄明白String.Index的用法,总结一下

开始索引和结束索引 startIndex and endIndex

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var str = "Hello, playground"

str.characters.count // 17

// startIndex 为字符串第一个字符的索引
let startIndex = str.startIndex // 0

// endIndex 为最后一个字符后面一个索引,这里跟数组索引不一样
let endIndex = str.endIndex // 17

// 直接截取第一个字符
str[startIndex] // H

str[endIndex] // 超出边界了 error

let allRange = startIndex..<endIndex // 整段字符的range
str[allRange] // Hello, playground 等同于 str.substring(with: allRange)

after
index(after: String.Index)
返回给定索引后面的一个索引

1
2
3
4
5
let afterIndex = str.index(after: startIndex) // 1
str[afterIndex] // "e"

var range = str.index(after: startIndex)..<endIndex
str[range] // ello, playground

before
index(before: String.Index)
返回给定索引前面的一个索引

1
2
3
let beforeEndIndex = str.index(before: endIndex)
range = startIndex...beforeEndIndex
str[range] // Hello, playground 对比 startIndex..<endIndex

offsetBy
index(String.Index, offsetBy: String.IndexDistance)
offsetBy值可以为正或负,并从给定索引开始。虽然它是String.IndexDistance类型,String.IndexDistance 就是Int,所以可以给定一个往前(正数)或者往后(负数)的偏移量。

1
2
3
4
5
6
7
let offsetStartIndex = str.index(str.startIndex, offsetBy: 2)

str.substring(to: offsetStartIndex) // He

let offsetEndIndex = str.index(endIndex, offsetBy: -3)

str[offsetStartIndex...offsetEndIndex] // llo, playgrou, 为什么只截去了尾部的nd?因为endIndex是结束字符的后一个索引

上面如果把offsetBy: 2改为offsetBy: 20,这个时候就越界了,如何在实际项目中避免越界引起的崩溃呢?limitedBy出场

limitedBy

index(String.Index, offsetBy: String.IndexDistance, limitedBy: String.Index)
limitedBy 对于确保偏移量不越界是很有用的,这个方法返回值可选,当加上偏移量越界以后,此方法会返回nil,这种对于不能确定字符长度和偏移量是否越界的时候可以进行安全判断。

1
2
3
4
5
6
7
8
9
10
if let limitedIndex = str.index(startIndex, offsetBy: 2, limitedBy: endIndex) {
    str.substring(to: limitedIndex) // He 没有越界,正常截取
}

if let limitedIndex = str.index(startIndex, offsetBy: 20, limitedBy: endIndex) {
    str.substring(to: limitedIndex) // will not execute, out of index
}
else {
    print("out of index") // 这里会输出 out of index
}

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注