Swift 的range比NSRange更加復(fù)雜,并且它在Swift3中并沒(méi)有變的更加容易。如果你想更加透徹的明白復(fù)雜的原因,你可以閱讀這還有這。我僅僅告訴你如何創(chuàng)建和使用它們。
Closed Ranges: a...b
這個(gè)區(qū)間表達(dá)式創(chuàng)建了一個(gè)Swift的range,該表達(dá)式包含元素a和元素b,即使可能為某個(gè)類(lèi)型的最大值(例如Int.max)。關(guān)于closed range有兩個(gè)類(lèi)型:CloseRange和CountableCloseRange。
-
ClosedRange
該區(qū)間的所有元素是可比較的在Swift中(它們遵守Comparable協(xié)議)。
它會(huì)允許你訪問(wèn)一個(gè)集合中某區(qū)間的元素。代碼示例:
let myRange: ClosedRange = 1...3
let myArray = ["a", "b", "c", "d", "e"]
myArray[myRange] // ["b", "c", "d"]
但是,ClosedRange是不可計(jì)算的(它沒(méi)有遵守Sequence協(xié)議)。這就意味你不能迭代該區(qū)間的值通過(guò)一個(gè)循環(huán),如果你想循環(huán)訪問(wèn)某個(gè)區(qū)間的值你需要使用CountableClosedRange類(lèi)型。
-
CountableClosedRange
該類(lèi)型可迭代循環(huán)。
//此處換成ClosedRange會(huì)報(bào)錯(cuò)
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
該區(qū)間表達(dá)式包含a但不包括b,和上面一樣,它也有兩個(gè)不同的類(lèi)型:Range和CountableRange
-
Range
和CloseRange一樣,你可以在一個(gè)集合中訪問(wèn)某區(qū)間的元素,示例代碼:
let myRange: Range = 1..<3
let myArray = ["a", "b", "c", "d", "e"]
myArray[myRange] // ["b", "c"]
重要的事再說(shuō)一次,該類(lèi)型不可應(yīng)用于for循環(huán)語(yǔ)句!
-
CountableRange
該類(lèi)型可應(yīng)用于for循環(huán)語(yǔ)句
let myRange: CountableRange = 1..<3
let myArray = ["a", "b", "c", "d", "e"]
myArray[myRange] // ["b", "c"]
for index in myRange {
print(myArray[index])
}
NSRange
有的時(shí)候你仍然需要使用NSRange在Swift(eg:當(dāng)你創(chuàng)建富文本的時(shí)候),所以了解如何創(chuàng)建它也是非常有用的。
let myNSRange = NSRange(location: 3, length: 2)
在這里強(qiáng)調(diào)一下上面的表達(dá)式代表的是location和length,并不是start index和end index。上面的例子和Swift中3..<5看起來(lái)非常相似。但是,它倆是不同的,它們并不能互相替換使用。
Ranges with Strings
通過(guò)...和..<創(chuàng)建ranges是非常方便的方法。代碼示例:
let myRange = 1..<3
比較苦逼的創(chuàng)建方式(作用和上面的代碼是一樣的):
let myRange = CountableRange<Int>(uncheckedBounds: (lower: 1, upper: 3)) // 1..<3
Problem with NSRange
NSRange在截取含有emoji字符的字符串時(shí),會(huì)出現(xiàn)錯(cuò)誤。
代碼示例:
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的計(jì)算是基于一個(gè)特殊的string,所以它能識(shí)別string中含有emoji或者其他的擴(kuò)展字體集。
代碼示例:
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"