在之前的文章中,你学习了swift编程语言的一些基础,如果你有过变成的经验,我确定你能看到一些和其他编程语言,例如ruby,js和oc相通的地方。
在这篇文章中,我们聚焦于swift中的控制流。在我们开始讨论控制流之前,我们来看一个对于大多数人来说挺陌生的概念,optionals。optionals是swift的另一个安全特色。
Optionals
我们已经看到过变量必须被初始化后才能被使用。看一下下面的例子就能更好的理解这是什么意思
var str:String
str.isEmpty
如果你和oc中的字符串打过交道,你会对swift抛出错误感到吃惊,让我们看看这个错误告诉了我们什么。
在很多语言中,变量有初始的默认值,在oc中,字符串在下面的代码中为nil
NSString *newString;
然而,nil的概念在oc和swift是不同的,我们在后面会详细讨论nil。
What is an optional?
swift使用optionals来封装一个重要的概念,就是,一个变量或者常量有一个值或者没有。在swift中就是这么简单。声明一个变量或者常量为optional,我们在常量或者变量的类型后附加一个问号。
var str:String?
这个str变量不再是String类型。它现在的类型是optional String,理解这个非常重要,这个类型的结果就是我们不再直接和变量str的值打交道。value存储在optional中非常安全,我们需要询问optional,它所封装的值是什么。
Forced Unwrapping
访问optional值的一个方法是通过forced unwrapping。我们可以通过附加!在变量名后来访问str的值。
var str:String?
str="Test"
println(str!)
你需要确保这个optional含有值才能forced unwrap。如果optional没有值而你forced unwrap,swift会抛出错误。
optional Binding
还有一种更安全的方法来访问optional的值。下面的例子像我们显示了如何安全的访问optional的值
var str:String?
if str != nil{
println(str!)
}else{
println("str has no value")
}
我们在输出str的内容前首先检查str是不是nil,在这个例子中,str没有值,意味着不会被强制解捆
还有一种更优雅的方法叫optional binding。在下面的例子中,我们将optional中的值赋给一个临时常量,这个临时常量在if语句中。optional str的值绑定在常量strConst中,并且使用在if语句。
var str:String?
str="Test"
if let strConst=str{
println(strConst)
}else{
println("str has no value")
}
What is nil?
如果你有oc的背景,你一定知道nil是什么。在oc中,nil是一个指向不存在对象的指针。swift将nil定义的有点点不同,你需要理解这个差异。
在swift中,nil意味着value的缺失。在oc中,nil只适用与对象,在swift中,nil可以是任何类型。所以要理解optional可不是oc中nil的等价物。这些概念非常不一样。
Control Flow
Swift提供了许多常用的结构帮助你控制代码的流向。如果你有编程的经验,你会对Swift的控制流结构没有任何问题,条件if和switch语句,for和whild的循环语句。
然而,Swift的控制流如果和oc的控制流没有一点点区别,Swift也就不是Swift了。尽管这些细节非常重要,我确信它们不会阻碍你学习Swift。让我们以最常见的条件结构,if语句开始。
if
swift的if语句和oc的if语句非常相似。主要的不同是不需要再用括号缠裹条件,然而大括号仍然是强制的。
let a=10
if a>10{
println("The value of \"a\" is greater than 10.")
}else{
println("The value of \"a\" is less than or equal to 10.")
}
有一个需要注意的是,if语句的返回值需要是false或者true。在oc里面没有这样的要求,看一下下面这个oc的例子
NSArray *array=@[];
if(array.count){
}else{
}
如果我们将上面的代码块移植到Swift,我们会得到错误。错误信息不是很有信息含量,但是Swift告诉我们需要确保条件的返回值是true或者false。
将上面oc的代码片段翻译成Swift的正确做法是将if语句的条件改为false或者true,正如下面的代码片段
let array=[String]()
if array.count>0{
}else{
}
Switch
Swift的switch语句比oc的switch语句更强大并且更安全。尽管有一些不同,Swift的switch语句遵守其他编程语言的相同概念。一个值传到switch语句,并且和可能的匹配模式相比较。
Exhaustive
Swift中的switch需要消耗完这个传进来的值,意味着这个值的所有可能都需要被处理。在oc中,只需要加一个default
let a=10
switch a{
case 0:
println("a is equal to 0")
case 1:
println("a is equll to 1")
default:
println("a has another value")
}
Fallthrough
一个相比oc很重要的差别是隐式穿越的缺失。下面的例子在Swift中无法工作
let a=10
switch a{
case 0:
case 1:
println("a is equal to 1")
default:
println("a has another value")
}
a和0的比价不会穿过第二个a与1的比较。如果你敲入上面的例子,你会得到一个错误。错误说每一个case需要至少一个可执行语句。
注意switch的case不包含break语句,swift中不是必须的因为隐式的通过不存在。
Patterns
Swift中switch语句的强大在于模式匹配。看一下下面的例子
let a=10
switch a
{
case 0..<5:
println("The value of a lies between 0 and 4.")
case 5...10:
println("The value of a lies between 5 and 10.")
default:
println("The value of a is greater than 10.")
}
..<操作符或者半开范围操作符定义,…操作符或者闭合范围操作符。
你可以比较元组和条件,看一下下面的例子
let latlng=(34.15,-78.03)
switch latlng
{
case (0,0):
println("We're at the center of the planet")
case (0...90,_):
println("We're in the Northern hemisphere.")
case (0...-90,_):
println("We're in the Southern hemisphere.")
default:
println("The coordinate is invalid.")
}
正如你看到的上面的例子,有可能这个value匹配了不止一种case。当这样的情况发生时,第一种匹配的case被选择。上面的例子也阐述了下划线的使用,我们可以使用下划线告诉Swift我们不感兴趣的value。
Value Binding
Value binding在switch语句中也是可能的。下面的例子说明了这一点,元组的第二个值暂时性的bound到了description常量上。
var response=(200,"OK")
switch response
{
case (200..<400,let description)
println("The request was successful with description \(description).")
case (400..<500,let description)
println("The request was unsuccessful with description \(description).")
default:
println("The request was unsuccessful with no description.")
}
for
for循环式我们要看的第一个循环结构。它和其他语言中的for循环非常类似。有两种不同的风味,for循环和for-in循环
for
swift中的for循环和oc中的for循环几乎一样。
for var i=0;i<10;i++{
println("i is equal to \(i).")
}
和if语句一样,没有需要用括号包含循环的初始化,条件和增加定义。循环语句,需要用大括号包裹。
for-in
for-in循环适合循环collection或者范围。在下面的例子中,我们循环了数组中的元素。
let numbers=[1,2,3,4,5]
for number in numbers{
println("number is equal to \(number)")
}
我们可以使用for-in来循环字典的键值对。在下面的例子中,我们声明了一个字典,将其内容打印到控制台。
var bids=["Tom":100,"Bart":150,"Susan":120]
for (name,bid) in bids}{
println("\(name)'s bid is $\(bid).")
}
字典里的键值对在for-in中都是以元组来访问的。
for i in 1...10{
println("i is equal to \(i)")
}
while
while循环也有两个变种,while和do-while。主要区别就是do-while的语句至少执行一次,因为do-while的条件总是在每一次迭代后评估
var c=5
var d=5
while c<d{
println("c is smaller than d")
}
do{
println("c is smaller than d")
}
while c<d
Conclusion
Swift的控制流远远不止我们在这篇文章中讨论的这些,但是你现在有一些基础可以继续你的Swift旅程。我希望这个教程向你传输了Swift的控制流和其他语言中的控制流非常相似,只有一点点调整。
在余下的系列中,我们会利用Swift的控制流结构。你会逐渐对Swift和其它类似oc的语言间的差别有更好的理解。在下一个教程中,我们开始探索函数。