我昨天下载了Xcode 8.0测试版,因此下载了Swift 3.我做的第一件事就是尝试更新我的Swift 3项目,我几乎哭了。其中一个最严重的变化是(在我看来)Swifts Range
struct的新管理,特别是因为自动转换为当前的Swift语法对范围没有任何作用。
Range
分为Range
,CountableRange
,ClosedRange
和CountableClosedRange
在考虑现在的情况时有意义使用范围时可能会出现这种情况(虽然它几乎是不必要的)。
但是:我有很多函数接受Range<Int>
作为参数或返回Range<Int>
。问题是:我通过0..<5
或0...4
调用了这些函数(因为它在语义上有时更具表现力)。当然,我可以简单地调整这些类型的东西。但为什么不是所有这些范围类型都有一个共同的界面?我必须为每个范围类型重载每个函数,并且每次都会执行完全相同的操作。
在Swift 3中使用范围还有最佳实践吗?
答案 0 :(得分:15)
关闭范围运算符(a...b)
定义从a
到b
的范围,并包含值a
和b
。 a
的值不得大于b
。
当您想要使用所有值的范围内进行迭代时,闭合范围运算符非常有用,例如使用for-in循环:
for index in 1...5 {
print("\(index) times 5 is \(index * 5)")
}
// 1 times 5 is 5
// 2 times 5 is 10
// 3 times 5 is 15
// 4 times 5 is 20
// 5 times 5 is 25
半开放范围运算符(a..<b)
定义了从a
到b
的范围,但不包括b
。它被认为是半开放的,因为它包含它的第一个值,但不是它的最终值。与闭区域运算符一样,a
的值不得大于b
。如果a
的值等于b
,则结果范围将为空。
半开放范围在使用基于零的列表(如数组)时特别有用,其中计算列表长度(但不包括)非常有用:
let names = ["Anna", "Alex", "Brian", "Jack"]
let count = names.count
for i in 0..<count {
print("Person \(i + 1) is called \(names[i])")
}
// Person 1 is called Anna
// Person 2 is called Alex
// Person 3 is called Brian
// Person 4 is called Jack
请注意,该数组包含四个项目,但0..<count
仅计算3
(数组中最后一项的索引),因为它是半开放范围。
a...b
let myRange = 1...3
let myArray = ["a", "b", "c", "d", "e"]
myArray[myRange] // ["b", "c", "d"]
a..<b
let myRange = 1..<3
let myArray = ["a", "b", "c", "d", "e"]
myArray[myRange] // ["b", "c"]
这是一个真实世界的SpriteKit示例,我必须使用arc4Random转换,几乎所有的SpriteKit项目都是如此。随机经常处理范围。
Swift 2
Tools.swift
func randomInRange(_ range: Range<Int>) -> Int {
let count = UInt32(range.upperBound - range.lowerBound)
return Int(arc4random_uniform(count)) + range.lowerBound
}
GameScene.swift
let gap = CGFloat(randomInRange(StackGapMinWidth...maxGap))
Swift 3
Tools.swift
func randomInRange(range: ClosedRange<Int>) -> Int {
let count = UInt32(range.upperBound - range.lowerBound)
return Int(arc4random_uniform(count)) + range.lowerBound
}
GameScene.swift
let gap = CGFloat(randomInRange(range: StackGapMinWidth...maxGap))
因此,如果randomInRange()
计算给定范围内的随机数,包括上限,则应将其定义为ClosedRange<Bound>
Range
和ClosedRange
无法迭代(它们不再是集合),因为仅Comparable
的值不能递增。
CountableRange
和CountableClosedRange
需要Strideable
,并且符合Collection
,以便您可以对其进行迭代。
答案 1 :(得分:14)
实际上非常简单:
使用三个点生成Array
(
[0] => Array
(
[name] => Afghanistan
[code] => AF
)
[1] => Array
(
[name] => Åland Islands
[code] => AX
)
[2] => Array
(
[name] => United Kingdom
[code] => GB
)
)
:Closed...Range
。这包括下限和上限。相反的是非闭合范围,由0...10
产生,不包括上限。
0..<10
是您可以使用有符号整数划分的类型范围,它由Countable...Range
或0...10
生成。这些类型符合0..<10
协议。
一些例子:
Sequence
根据您的需要,您应该让您的方法接受通用0..<10 // CountableRange
0...Int.max // CountableClosedRange (this was not possible before Swift 3)
"A"..<"A" // Range, empty
"A"..."Z" // ClosedRange, because cannot stride through, only check if a character is in the bounds
/ Collection
:
Sequence
也许您可以展示func test<C: Collection where C.Iterator.Element == Int>(s: C) {
print(s.first)
}