Swift-Range

Swift 的range比NSRange更加复杂,并且它在Swift3中并没有变的更加容易。如果你想更加透彻的明白复杂的原因,你可以阅读还有。我仅仅告诉你如何创建和使用它们。

Closed Ranges: a...b

这个区间表达式创建了一个Swift的range,该表达式包含元素a和元素b,即使可能为某个类型的最大值(例如Int.max)。关于closed range有两个类型:CloseRangeCountableCloseRange

  • ClosedRange
    该区间的所有元素是可比较的在Swift中(它们遵守Comparable协议)。

它会允许你访问一个集合中某区间的元素。代码示例:

1
2
3
let myRange: ClosedRange = 1...3
let myArray = ["a", "b", "c", "d", "e"]
myArray[myRange] // ["b", "c", "d"]

但是,ClosedRange是不可计算的(它没有遵守Sequence协议)。这就意味你不能迭代该区间的值通过一个循环,如果你想循环访问某个区间的值你需要使用CountableClosedRange类型。

  • CountableClosedRange
    该类型可迭代循环。
1
2
3
4
5
6
7
//此处换成ClosedRange会报错
let myRange: CountableClosedRange = 1...3
let myArray = ["a", "b", "c", "d", "e"]
myArray[myRange] // ["b", "c", "d"]
for index in myRange {
print(myArray[index])
}
Half-Open Range:a..<b

该区间表达式包含a但不包括b,和上面一样,它也有两个不同的类型:RangeCountableRange

  • Range
    CloseRange一样,你可以在一个集合中访问某区间的元素,示例代码:
1
2
3
let myRange: Range = 1..<3
let myArray = ["a", "b", "c", "d", "e"]
myArray[myRange] // ["b", "c"]

重要的事再说一次,该类型不可应用于for循环语句!

  • CountableRange
    该类型可应用于for循环语句
1
2
3
4
5
6
let myRange: CountableRange = 1..<3
let myArray = ["a", "b", "c", "d", "e"]
myArray[myRange] // ["b", "c"]
for index in myRange {
print(myArray[index])
}
NSRange

有的时候你仍然需要使用NSRange在Swift(eg:当你创建富文本的时候),所以了解如何创建它也是非常有用的。

1
let myNSRange = NSRange(location: 3, length: 2)

在这里强调一下上面的表达式代表的是locationlength,并不是start indexend index。上面的例子和Swift中3..<5看起来非常相似。但是,它俩是不同的,它们并不能互相替换使用。

Ranges with Strings

通过.....<创建ranges是非常方便的方法。代码示例:

1
let myRange = 1..<3

比较苦逼的创建方式(作用和上面的代码是一样的):

1
let myRange = CountableRange<Int>(uncheckedBounds: (lower: 1, upper: 3)) // 1..<3
Problem with NSRange

NSRange在截取含有emoji字符的字符串时,会出现错误。

代码示例:

1
2
3
4
5
let myNSRange = NSRange(location: 1, length: 3)
let myNSString: NSString = "abcde"
myNSString.substring(with: myNSRange) // "bcd"
let myNSString2: NSString = "a😀cde"
myNSString2.substring(with: myNSRange) // "😀c" Where is the "d"!?
Swift Solution

由于以上的原因,在Swift中的字符串你需要使用Range<String.Index>而不是Range<Int>。String Index的计算是基于一个特殊的string,所以它能识别string中含有emoji或者其他的扩展字体集。

代码示例:

1
2
3
4
5
6
7
8
9
10
var myString = "abcde"
let start = myString.index(myString.startIndex, offsetBy: 1)
let end = myString.index(myString.startIndex, offsetBy: 4)
let myRange = start..<end
myString.substring(with: myRange) // "bcd"
myString = "a😀cde"
let start2 = myString.index(myString.startIndex, offsetBy: 1)
let end2 = myString.index(myString.startIndex, offsetBy: 4)
let myRange2 = start2..<end2
myString.substring(with: myRange2) // "😀cd"

原文链接