Control Flow指的是『逻辑控制语句』,包括if、if-else、for、for-in、while、do-while、switch等。其中大部分和OC中差不多,但Swift在某些方便增强了控制语句的功能。譬如for-in中引入..<...操作符;switch语句更是大不一样了。本文也只针对for-in和switch语句展开阐述。

For-In

for-in语句基本上和OC中的for-in语句被太多区别,但新增了两个符号:..<(类似于Python中的range())和...

  • ..<描述的区间是半闭区间(左闭右开),即0..<2表示[0,2)(0<=x<2,其中x为整数);
  • ...描述的区间是全闭区间(左闭右闭),即0...2表示[0,2](0<=x<=2,其中x为整数);

P.S:Swift刚开始推出来的时候,..<的原型是..,好在很快在后续版本中改成了..<,否则实在是个灾难!看着一门语言一点点进步,最后发展成一门伟大的语言是一件挺棒的事情,Swift会发展成一门伟大的语言吗?我想会!
P.S:我个人觉得...不是一个很好的设计,为什么要这么一个操作符呢?希望以后能找到答案吧!

Switch

Switch语句和if语句都属于条件语句,switch会尝试把某个值与若干个模式(pattern)进行匹配。根据第一个匹配成功的模式,switch语句会执行对应的代码。当有可能的情况较多时,通常用switch语句替换if语句,如下:

switch someValueToConsider {
case value1:
// respond to value1
case value2, value3:
// respond to value2 or value3
default:
// otherwise, do something else
}

switch语句都由多个case构成。为了匹配某些更特定的值,Swift提供了几种更复杂的匹配模式,这些模式将在本节的稍后部分提到。

Swift规定switch语句必须是「完备的」。这就是说,每一个可能的值都必须至少有一个case块与之对应。在某些不可能涵盖所有值的情况下,你可以使用默认default块满足该要求,这个默认块必须在switch语句的最后面。

不存在隐式fallthrough

在C和OC中,写switch语句时,一定要确保在每个case语句的末尾添加一句break;,这样才能确保switch代码块终止,否则会执行下一个case/default块,这种行为在Swift中被称为「fallthrough」。

与C语言和OC中的switch语句不同,在Swift中,当匹配的case块中的代码执行完毕后,程序会自动终止switch语句,而不会继续执行下一个case块。这也就是说,不需要在case块中显式地使用break语句,这使得switch语句更安全、更易用,也避免了因忘记写break语句而产生的错误。

除此之外,Swift还规定每一个case语句中都必须包含至少一条语句,像下面这样书写代码是无效的,因为第一个case块是空的:

let anotherCharacter: Character = "a"
switch anotherCharacter {
case "a":
case "A":
println("The letter A")
default:
println("Not the letter A")
}
// this will report a compile-time error

一个case也可以包含多个匹配模式,不同的pattern用逗号,分开。

范围匹配

case块的pattern可以是一个范围,如下:

let count = 3_000_000_000_000
let countedThings = "stars in the Milky Way"
var naturalCount: String
switch count {
case 0:
naturalCount = "no"
case 1...3:
naturalCount = "a few"
case 4...9:
naturalCount = "several"
case 10...99:
naturalCount = "tens of"
case 100...999:
naturalCount = "hundreds of"
case 1000...999_999:
naturalCount = "thousands of"
default:
naturalCount = "millions and millions of"
}
println("There are \(naturalCount) \(countedThings).")
// prints "There are millions and millions of stars in the Milky Way."

元组

你可以使用元组在同一个switch语句中测试多个值。元组中的元素可以是值,也可以是范围。另外,使用下划线_来匹配所有可能的值,如下例子展示了如何使用(Int, Int)类型的元组来分类下图中的点(x, y)

let somePoint = (1, 1)
switch somePoint {
case (0, 0):
println("(0,0) is at the origin")
case (_, 0):
println("(\(somePoint.0), 0) is on the x-axis")
case (0, _):
println("(0, \(somePoint.1)) is on the y-axis")
case (-2...2, -2...2):
println("(\(somePoint.0), \(somePoint.1)) is inside the box")
default:
println("(\(somePoint.0), \(somePoint.1)) is outside of the box")
}
// prints "(1, 1) is inside the box"

在上面的例子中,switch 语句会判断某个点是否是原点(0, 0),是否在红色的x轴上,是否在黄色y轴上,是否在一个以原点为中心的4x4的矩形里,或者在这个矩形外面。

不像C语言,Swift允许多个case匹配同一个值。实际上,在这个例子中,点(0, 0)可以匹配所有四个case。但是,如果存在多个匹配,那么只会执行第一个被匹配到的case块。考虑点(0, 0)会首先匹配case (0, 0),因此剩下的能够匹配(0, 0)的case块都会被忽视掉。

Value Bindings

在多个值匹配(使用tuple)时,我们常常会需要用到被检测值的局部值,switch语句还允许在case中进行value binding,如下:

let anotherPoint = (2, 0)
switch anotherPoint {
case (let x, 0):
println("on the x-axis with an x value of \(x)")
case (0, let y):
println("on the y-axis with an y value of \(y)")
case (x, y):
println("somewhere else at (\(x), \(y))")
}
// prints "on the x-axis with an x value of 2"

这个例子中,switch语句会判断某个点是否在x轴和y轴上,或者在别的地方。

Where语句

Swift中还有一个关键字where,常用来处理更复杂的模式匹配;在case中使用where关键字引导的where语句可以用来判断额外的条件:

let yetAnotherPoint = (1, -1)
switch yetAnotherPoint {
case let (x, y) where x == y:
println("\(x), \(y) is on the line x == y")
case let (x, y) where x == -y:
println("\(x), \(y) is on the line x == -y")
case let (x, y):
println("\(x), \(y) is just some arbitrary point")
}

这个例子中,switch语句会判断某个点是否在绿线(y=x)上,是否在紫线(y=-x)上,或者不在对角线上。

控制转移语句

控制转移代码能改变你代码的执行顺序,通过它你可以控制代码的跳转,在Swift中,有四种控制转移语句:

  • continue
  • break
  • fallthrough
  • return

除此之外,Swift还引入「labeled statements」,用来帮助更灵活的控制转移。

continue、break、return这几个控制语句与我们在C、OC中所了解的控制语句相比没啥不同,这里就不赘述了;所以本节内容包括:

  • switch与break;
  • switch与fallthrough;
  • labeled statements;

switch与break

上文已经提到,在C和OC中,常常需要在case块后面添加break;代码,因为如果不这样,switch语句就紧接着执行后续的case语句(注意,后续的case pattern可不会被检查啊,而是直接执行后续case的body代码);但在Swift中,不需要这样,因为在Swift的switch语句中,当匹配的case块中的代码执行完毕后,程序会自动终止switch语句,而不会继续执行下一个case块。

所以按理说是不需要在switch语句中显式使用break指令的。但事实并非这样,因为Swift还有一个要求,规定每一个case语句中都必须包含至少一条语句。然而,在某些情况下的某些case分支里,可能真的啥都不想干,其他语言使用;了事,但Swift语句中不需要使用;,此时一般使用break语句代替,如下:

let numberSymbol: Character = "三" // Simplified Chinese for the number 3
var possibleIntegerValue: Int?
switch numberSymbol {
case "1", "١", "一", "๑":
possibleIntegerValue = 1
case "2", "٢", "二", "๒":
possibleIntegerValue = 2
case "3", "٣", "三", "๓":
possibleIntegerValue = 3
case "4", "٤", "四", "๔":
possibleIntegerValue = 4
default:
break
}

fallthrough

本节简单谈谈fallthrough,这可是新玩意儿。

上文已经多次提及,Swift语言中的switch不会从上一个case分支落入到下一个case分支中。相反,只要第一个匹配到的case分支完成了它需要执行的语句,整个switch代码块完成了它的执行。相比之下,C语言要求你显示的插入break语句到每个switch分支的末尾来阻止自动落入到下 一个case分支中。Swift语言的这种避免默认落入到下一个分支中的特性意味着它switch功能要比C语言的更加清晰和可预测,可以避免无意识地执行多个case分支从而引发的错误。

但有时候确实需要人为的fallthrough,此时fallthrough关键字就派上用场了,如下:

let integerToDescribe = 5
var description = "The number \(integerToDescribe) is"
switch integerToDescribe {
case 2, 3, 5, 7, 11, 13, 17, 19:
description += "a prime number, and also"
fallthrough
default:
description += " an integer"
}
println(description)
// prints "The number 5 is a prime number, and also an integer."

值得一提的是,fallthrough关键字不会检查它下一个将会落入执行的case中的匹配条件。fallthrough简单地使代码执行继续连接到下一个case中的执行代码,这和C语言标准中的switch语句特性是一样的。

Labeled Statements

在Swift语言中,你可以在循环体(for循环或while循环)和switch代码块中嵌套循环体和switch代码块来创造复杂的控制流结构。然而,循环体和switch代码块两者都可以使用break 语句来提前结束整个代码块。因此,显示地指明break语句想要终止的是哪个循环体或者switch代码块会很有用。类似地,如果你有许多嵌套的循环体,显示指明continue语句想要影响哪一个循环体也会非常有用。

为了实现这个目的,你可以使用标签来标记一个循环体或者switch代码块,当使用break或者continue时,带上这个标签,可以控制该标签代表对象的中断或者执行。

产生一个带标签的语句是通过在该语句的关键词的同一行前面放置一个标签,并且该标签后面还需带着一个冒号。下面是一个while循环体的语法,同样的规则适用于所有的循环体和switch代码块:

labelName: while condition {
// statements
}

label的使用非常简单,如下有一段代码演示了label的应用:

gameLoop: while square != finalSquare {
if ++diceRoll == 7 { diceRoll = 1 }
switch square + diceRoll {
case finalSquare:
// diceRoll will move us to the final square, so the game is over
break gameLoop
case let newSquare where newSquare > finalSquare:
// diceRoll will move us beyond the final square, so roll again
continue gameLoop
default:
// this is a valid move, so find out its effect
square += diceRoll
square += board[square]
}
}
println("Game over!")

显然,labeled statements可以实现类似于C语言中goto语句的功能。

Swift 控制语句的更多相关文章

  1. Swift控制语句

    前言 Swift提供了类似C语言的流程控制结构,包括可以多次执行任务的for和while循环.还有基于特定条件选择执行不同代码分支的if.guard和switch语句,还有控制流程跳转到其他代码的br ...

  2. 学习swift从青铜到王者之Swift控制语句04

    1 if语句基本用法 if boolean_expression { /* 如果布尔表达式为真将执行的语句 */ } 如果布尔表达式为 true,则 if 语句内的代码块将被执行.如果布尔表达式为 f ...

  3. Swift编程语言学习4.3—— 控制语句

    控制传递语句(Control Transfer Statements) 控制转移语句改变你代码的运行顺序,通过它你能够实现代码的跳转.Swift有四种控制转移语句. continue break fa ...

  4. swift 上手

    学习swift的笔记,偶尔会更新一下 变量与常量 变量定义使用var,常量使用let,类型安全,有自动类型推导,注意赋值的=号两边必须有空格. 变量和常量名是可以几乎所有字符,这些都非常像javasc ...

  5. swift基础:第三部分:对第一部分的补充说明

    今天是我学习swift的第二天,虽然我和swift的距离有点远,但我相信,我会慢慢的接近这门语言的.好了,我们聊聊昨天晚上的事吧,昨天晚上下班早,回到家时,真是惊喜哈,宿舍那两做好了饭,等我吃饭,想对 ...

  6. swift基础:第二部分:函数和闭包

    今天本来想利用上午的时间本来打算将swift基础部分学习完的,不巧的是,后台来和我讨论用户评价的接口,讨论过后,商讨出一种可行的方案,十几分钟时间过去了,我拿到将接口介入到已经完成的页面中,完美,终于 ...

  7. Swift语法简介(一)

    或许网络上有很多成型的介绍,我只想写下来留给自己.欢迎批评.开撸! 1.第一个程序,Hello,world!古人云,学会了Hello,world!这门语言你就掌握了一半了. print("H ...

  8. Swift的基本类型和流程控制

    Swift  是一门静态的强类型语言.它以简单.干净.可读性好等特点著称. 1. 为什么是静态语言? 首先静态语言比之动态语言,更具有安全性.它不允许类型之间自动的进行转换,必须要显示的转换.Swif ...

  9. [IOS]《A Swift Tour》翻译(一)

    以下翻译内容为原创,转载请注明: 来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/3768936.html 碎碎念... Swift是苹果在WWDC刚发 ...

随机推荐

  1. [WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!

    一.背景 最近的项目在用maven 进行install的时候,发现老师在控制台输出警告:[WARNING] Using platform encoding (UTF-8 actually) to co ...

  2. Direct2D教程(九)渲染位图

    概述 这篇的标题更确切的说应该叫位图画刷,这样才好和前几篇对应起来.在Direct2D中,位图的渲染也是通过画刷来实现的. Direct2D中并没有直接操作位图的接口,而是借助WIC(Windows ...

  3. HDU 5054 Alice and Bob(数学)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5054 Problem Description Bob and Alice got separated ...

  4. Win7如何自定义鼠标右键菜单 添加新建PowerPoint文档

    鼠标右键添加新建PowerPoint文档.reg Windows Registry Editor Version 5.00 [HKEY_CLASSES_ROOT\.ppt] "Content ...

  5. 【转载】How to develop your own Boot Loader【怎么样开发自己的bootloader】

    How to develop your own Boot Loader 怎么样开发自己的bootloader Table of content[目录] 1. Who may be interested ...

  6. Linux高端内存

    Linux高端内存是针对物理内存来说的,虚拟内存没有高端这个概念.Linux系统将虚拟内存分为两个部分,即用户地 址空间和内核地址空间,对于32位系统来说,虚拟地址空间为4GB,其中用户空间范围为0- ...

  7. 【ZZ】Visual C++ 6.0 精简安装版(支持VA、ICC 等等安装)

    (2012-04-22 08:10:10) 标签: it 分类: 软件_Software Visual C++ 6.0 精简安装版(支持VA.ICC 等等安装) 2012-04-16 21:07 想找 ...

  8. mnesia练习及基本操作

    Mnesia基本用法 查看表结构 查看mnesia表的结构: mnesia:info(). 查看此表的基本信息: mnesia:table_info(<tableName>, all). ...

  9. FFmpeg解码详细流程

    FFmpeg在解码一个视频的时候的函数调用流程.为了保证结构清晰,其中仅列出了最关键的函数,剔除了其它不是特别重要的函数. 下面解释一下图中关键标记的含义. 函数背景色 函数在图中以方框的形式表现出来 ...

  10. 关于wpf中popup跟随鼠标移动显示

    最近在做一个画图工具,里面有一个功能是需要实现,当鼠标移动的时候在,鼠标的旁边显示坐标信息. 第一反应是想到了tooltip,但是tooltip有许多的限制,查询资料的过程中看到了popup,popu ...