Swift from Scratch: Optionals and Control Flow

在之前的文章中,你学习了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的语言间的差别有更好的理解。在下一个教程中,我们开始探索函数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值