IOS迷你教程3-Swift语言之流程控制(swift4.2)

告诉计算机在什么时候该做什么,称做控制流

在本教程中,您将学习如何来控制流程,从而让计算机听你的话。您还将了解布尔truefalse,以及如何使用它们来比较数据。

入门

此前学过了一些类型如IntDoubleString。在这里,您将学习另一种类型:布尔。

如,查找两个数字中的较大者,答案是truefalse

let yes = true // 类型推断为Bool
let no = false // 类型推断为Bool

布尔类型的值只能是truefalse

布尔运算符

布尔值通常用于比较值。例如,您可能有两个值,并且您想知道它们是否相等:值是相同的(true)还是它们是不同的(false)。

在Swift中,使用==执行此操作

let doesOneEqualTwo = (1 == 2)

swift推断doesOneEqualTwo是一个Bool。显然,1不等于2,因此doesOneEqualTwo将是false

同样,你可以看看两个值是否相等:

let doesOneNotEqualTwo = (1 != 2)

因为1不等于2,所以doesOneNotEqualTwo会是true

!取反操作

大于(>),小于(<):

let isOneGreaterThanTwo = (1 > 2)
let isOneLessThanTwo = (1 < 2)

isOneGreaterThanTwofalseisOneLessThanTwotrue

另外还有小于等于和大于等于:<=>=,同理。

布尔逻辑

&&。如果两个都是true,结果才是true。否则,结果是false

let and = true && true

在这种情况下,and将是true。如果右边的任何一个值是false,那么and就是false

||。只要其中一个为true,则结果为true。

let or = true || false

在这种情况下,or将是true。如果右边的两个值都是false,那么or就是false。如果两者都是true,那么or仍然是true

在Swift中,布尔逻辑通常应用于多个条件:

let andTrue = 1 < 2 && 4 > 3
let andFalse = 1 < 2 && 3 > 4

let orTrue = 1 < 2 || 3 > 4
let orFalse = 1 == 2 || 3 == 4

也可以这样:

let andOr = (1 < 2 && 3 > 4) || 1 < 4

字符串比较

在Swift,用于比较数字是否相等的==号也可以用来比较字符串:

let guess = "dog"
let dogEqualsCat = guess == "cat"

得出dogEqualsCat是一个布尔类型,为false

与数字一样,您不仅可以比较是否相等,还可以比较一个值是否大于或小于另一个值:

let order = "cat" < "dog"

这时是按英文字母顺序比较,ordertrue

if语句

流程控制的第一个也是最常见的是if,只有某个条件为true时才执行:

if 2 > 1 {
  print("Yes, 2 is greater than 1.")
}

这是一个简单的if语句。如果条件是true,则将执行大括号之间的代码。如果条件为false,则语句将不执行大括号之间的代码。

您可以扩展if语句:

let animal = "Fox"
if animal == "Cat" || animal == "Dog" {
  print("Animal is a house pet.")
} else {
  print("Animal is not a house pet.")
}

这里,如果animal等于"Cat"或者"Dog",那么语句将运行第一个代码块。如果animal不等于"Cat"或者"Dog",则将在else内运行,以下内容被打印到控制台:

Animal is not a house pet.

else if

let hourOfDay = 12
var timeOfDay = ""

if hourOfDay < 6 {
  timeOfDay = "Early morning"
} else if hourOfDay < 12 {
  timeOfDay = "Morning"
} else if hourOfDay < 17 {
  timeOfDay = "Afternoon"
} else if hourOfDay < 20 {
  timeOfDay = "Evening"
} else if hourOfDay < 24 {
  timeOfDay = "Late evening"
} else {
  timeOfDay = "INVALID HOUR!"
}
print(timeOfDay)

if语句将逐个测试多个条件,直到true。无论后面的else-if条件是否为true,仅执行第一条true后面的代码。

末尾的else子句来处理以上都为false的情况。

控制台将打印出以下内容:

Afternoon

封装变量

if语句引入了一个新的概念范围,这是一种通过使用大括号封装变量的方法。

如,某地兼职工资的规定为:在40小时之前每小时25美元,之后每小时50美元。

通过以下方式计算您的工资:

var hoursWorked = 45

var price = 0
if hoursWorked > 40 {
  let hoursOver40 = hoursWorked - 40
  price += hoursOver40 * 50
  hoursWorked -= hoursOver40
}
price += hoursWorked * 25

print(price)

结果如下:

1250

hoursOver40是在if语句中声明的新常量。如果这样会发生什么?

// ...

print(price)
print(hoursOver40)

这将导致以下错误:

Use of unresolved identifier 'hoursOver40'

此错误通知您,您只能在创建它的范围内使用hoursOver40常量。在这种情况下,if语句创建了一个新范围,因此当该范围结束后,您将无法使用该常量。

但是,每个范围都可以使用其父范围中的变量和常量。在上面的示例中,if语句内部仍然可以使用您在父范围中创建的pricehoursWorked变量。

三元运算

三元运算符即返回两个值中的一个,这取决于条件是true还是false

(<CONDITION>) ? <TRUE VALUE> : <FALSE VALUE>

这是一个找出两个变量中最小值的示例:

let a = 5
let b = 10

let min: Int
if a < b {
  min = a
} else {
  min = b
}

感谢三元运算符,您可以重写为简洁的代码:

let a = 5
let b = 10

let min = a < b ? a : b

如果a < btrue,则min的值为a;如果是falseminb

注意:如果过度使用,可能会牺牲代码的易读性。

循环

循环是多次执行代码的一种方式。在本节中,您将了解while循环。

循环时

while后面条件为true时,将循环执行大括号中的代码:

while <CONDITION> {
  <LOOP CODE>
}

每一次循环,都会先检查条件。如果条件是true,则执行并准备下一次循环。一旦条件为false,则循环停止。就像if语句一样,while循环也引入了一个范围(大括号中的代码)。

最简单的while循环:

while true {
}

这是一个永远不会结束的while循环(死循环),因为条件总是true。一个死循环可能不会让程序崩溃,但很可能会让计算机死机。

一个while循环示例:

var sum = 1

while sum < 1000 {
  sum = sum + (sum + 1)
}

此代码计算一个数学序列,直到sum值大于1000

循环执行如下:

在第九次迭代(循环)之后,sum1023,循环条件sum < 1000变为false,循环停止。

repeat-while循环

它与while循环的不同之处在于,在循环结束时判断条件是否为true

repeat {
  <LOOP CODE>
} while <CONDITION>

这是上一节的示例,使用repeat-while循环:

sum = 1

repeat {
  sum = sum + (sum + 1)
} while sum < 1000

在此示例中,结果和之前相同。但并非所有的时候都是一样的。

while循环:

sum = 1
while sum < 1 {
  sum = sum + (sum + 1)
}

repeat-while循环:

sum = 1
repeat {
    sum = sum + (sum + 1)
}while sum < 1

while循环中,条件从一开始就是false。说明不会执行循环体,sum最终为1

repeat-while中,sum3,因为循环体将先执行一次。

跳出循环

有时你想早点结束循环。可以使用break语句,该语句会立即停止循环并继续循环后面的代码:

sum = 1

while true {
  sum = sum + (sum + 1)
  if sum >= 1000 {
    break
  }
}

条件为true,所以会永远循环。但一旦sum大于或等于1000,循环将结束。

高级控制流

在本节中,您将继续学习如何控制代码执行。您将了解另一个称为for循环的循环。

范围

在深入了解for循环语句之前,您需要了解一下ClosedRangeRange类型,它们可以表示一系列的数字。

封闭的范围:

let closedRange = 0...5

三个点(...)表示范围是从0到5(包括0和5)。即0, 1, 2, 3, 4, 5

半开放范围:

let halfOpenRange = 0..<5

范围是从0到5,包括0但包括5。即0, 1, 2, 3, 4

注意:
第二个数字必须始终大于或等于第一个数字。
范围通常用于for循环和switch语句中!

for循环

for <CONSTANT> in <RANGE> {
  <LOOP CODE>
}

循环以for关键字开头,后面跟一个想在循环中使用的常量名,in后面为循环的范围:

let count = 10
var sum = 0

for i in 1...count {
  sum += i
}

i的初始值为1,也就是范围(1...count)的第一个数,每次循环之后都加1,直到等于count为止。

以下是每次迭代的isum的值:

i循环外部不可用。

当你在循环中不需要使用i时,可以用下划线:

sum = 1
var lastSum = 0

for _ in 0..<count {
  let temp = sum
  sum = sum + lastSum
  lastSum = temp
}

只是单纯的想让代码执行一定的次数,不需要用到循环常量(上述i)。
0..<count半开,表示代码将执行count次,这是一种需要执行多少次的常用方法。

也可以仅在某些条件下执行循环。如,想要计算总和但仅针对奇数:

var sum = 0
for i in 1...count where i % 2 == 1 {
  sum += i
}

wherefor循环中的一个子句。循环只会在where条件为true时执行循环体。

continue声明

有时你想跳过特定情况的循环迭代,而不想完全跳出循环。可以使用continue语句,该语句立即结束循环的当前迭代并开始下一次迭代。

8✕8乘法表:

full_board

假设您想要计算所有单元格的总和但排除所有偶数行:

first_board_example

使用for循环:

sum = 0

for row in 0..<8 {
  if row % 2 == 0 {
    continue
  }

  for column in 0..<8 {
    sum += row * column
  }
}

模2为0时,该行是偶数行。在这种情况下,continue跳出本次for循环,执行下一次循环。

break一样,continue也适用于for循环和while循环。

switch语句

控制流的另一种是switch语句,它允许您根据变量或常量的值执行不同的代码。

一个非常简单的switch语句:

let number = 10

switch number {
case 0:
  print("Zero")
default:
  print("Non-zero")
}

将输出:

Non-zero

case后面的值(本例中为0)表示:当number为此值时,执行冒号后面的语句。default表示以上全没有匹配到的话执行下面的代码。

另一个例子:

switch number {
case 10:
  print("It's ten!")
default:
  break
}

这次匹配到10,将执行case下面的代码。
break表示什么都不执行,

switch语句适用于任何数据类型!以下是切换字符串的示例:

let string = "Dog"

switch string {
case "Cat", "Dog":
  print("Animal is a house pet.")
default:
  print("Animal is not a house pet.")
}

这将打印以下内容:

Animal is a house pet.

case后接两个值,这说明如果等于"Cat"或者"Dog"将执行。

高级switch语句

case后接多种情况:

let hourOfDay = 12
var timeOfDay = ""

switch hourOfDay {
case 0, 1, 2, 3, 4, 5:
  timeOfDay = "Early morning"
case 6, 7, 8, 9, 10, 11:
  timeOfDay = "Morning"
case 12, 13, 14, 15, 16:
  timeOfDay = "Afternoon"
case 17, 18, 19:
  timeOfDay = "Evening"
case 20, 21, 22, 23:
  timeOfDay = "Late evening"
default:
  timeOfDay = "INVALID HOUR!"
}

print(timeOfDay)

将输出以下内容:
Afternoon

可以使用范围让代码更简洁:

var timeOfDay2 = ""

switch hourOfDay {
case 0...5:
  timeOfDay2 = "Early morning"
case 6...11:
  timeOfDay2 = "Morning"
case 12...16:
  timeOfDay2 = "Afternoon"
case 17...19:
  timeOfDay2 = "Evening"
case 20..<24:
  timeOfDay2 = "Late evening"
default:
  timeOfDay2 = "INVALID HOUR!"
}

print(timeOfDay2)

也可以像for循环一样使用where子句(先声明一个常量以便where子句中使用):

switch number {
case let x where x % 2 == 0:
  print("Even")
default:
  print("Odd")
}

这将打印以下内容:

Even

如for循环一样,声明的常量在下面的代码中不需要使用的话,可以用下划线代替:

switch number {
case _ where number % 2 == 0:
  print("Even")
default:
  print("Odd")
}

部分匹配

let coordinates = (x: 3, y: 2, z: 5)

switch coordinates {
case (0, 0, 0): // 1
  print("Origin")
case (_, 0, 0): // 2
  print("On the x-axis.")
case (0, _, 0): // 3
  print("On the y-axis.")
case (0, 0, _): // 4
  print("On the z-axis.")
default:        // 5
  print("Somewhere in space")
}

switch语句使用部分匹配

  1. 精确匹配(0, 0, 0)。说明时3D空间的原点。
  2. 匹配y = 0,z = 0和x可为任何值。说明坐标位于x轴上。
  3. 匹配x = 0,z = 0和y可为任何值。说明坐标位于y轴上。
  4. 匹配x = 0,y = 0和z可为任何值。说明坐标位于z轴上。
  5. 匹配其余坐标。

把上例中的下划线声明为变量,这样可以在case后面的语句中使用:

switch coordinates {
case (0, 0, 0):
  print("Origin")
case (let x, 0, 0):
  print("On the x-axis at x = \(x)")
case (0, let y, 0):
  print("On the y-axis at y = \(y)")
case (0, 0, let z):
  print("On the z-axis at z = \(z)")
case let (x, y, z):
  print("Somewhere in space at x = \(x), y = \(y), z = \(z)")
}

使用let语法来提取相关值。然后使用字符串插值打印出来。

switch语句中没有default选项。因为已经穷举了所有情况,所以不用写默认值。

注:想提取元组的所有值时,let (x, y, z)(let x, let y, let z)一样。

最后,可以使用let-where语法来匹配更复杂的情况:

switch coordinates {
case let (x, y, _) where y == x:
  print("Along the y = x line.")
case let (x, y, _) where y == x * x:
  print("Along the y = x^2 line.")
default:
  break
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,585评论 18 139
  • 第2章 基本语法 2.1 概述 基本句法和变量 语句 JavaScript程序的执行单位为行(line),也就是一...
    悟名先生阅读 4,114评论 0 13
  • 首先我想跟大家分享一个真实的事件:有一天太太回到家,看到先生躺在沙发上看电视,没有煮饭,于是说:“你这个懒鬼...
    NLPer彭慧阅读 436评论 0 1
  • 那天,当西北风把空气中看似雾霾的雾水都吹散后,香蕉怪兽的真身就展现在众人的眼前。每个路过的甲乙丙丁戊己庚辛,疑惑地...
    我叫两文钱阅读 528评论 0 0
  • 早晚有一天要把自己整死,我想过得更好,活的更好,我的那些同学们,那些高中同学们,都活的好有朝气,我也要那样蓬勃
    辣椒小柒阅读 195评论 0 0