已经完成了所有关于Swift基础的部分,感觉东西说多不多,说少也确实有一些部分理解起来有一些困难。从这天开始的三天为快速回顾(因为是快速回顾名,我只是浏览一遍唤醒记忆,直接摘录机器翻译,以后再人工校正):

变量和常量

每个有用的程序都需要在某个时刻存储数据,在Swift中,有两种方法可以存储数据:变量和常量。变量是可以随时更改其值的数据存储,而常量是可以设置一次且永不更改的数据存储。因此,变量的值可以变化,常量的值是恒定的-简单,对吧?

拥有这两个选项似乎毫无意义,毕竟你只能创建一个变量,然后再不更改它–为什么需要将其设为常量?好吧,事实证明,许多程序员都很震惊!–在编程方面还不完美,我们会犯错误。

分离常量和变量的优点之一是Xcode会告诉我们是否犯了错误。如果我们说“使该日期成为一个常数,因为我知道它永远不会改变”,那么在10行之后尝试更改它,Xcode将拒绝构建我们的应用程序。

常量也很重要,因为它们使Xcode可以决定其构建应用程序的方式。如果知道值永远不会改变,则可以应用优化以使代码运行更快。

在Swift中,你可以使用var关键字创建变量,如下所示:

1
var name = "Tim McGraw"

让我们将其放在操场上,以便你可以开始获得反馈。删除该import UIKit行中的所有内容(这是拉进苹果核心iOS框架的位,以后需要它),然后添加该变量。你应该看到下面的图片。

因为这是一个变量,所以你可以随时更改它,但是你不必var每次都使用关键字-仅在声明新变量时才使用。尝试这样写:

1
2
var name = "Tim McGraw"
name = "Romeo"

因此,第一行创建name变量并为其提供初始值,然后第二行更新name变量,以使其值现在为“ Romeo”。你会在操场的结果区域中看到两个值。

现在,如果我们将其设为常量而不是变量呢?好吧,常量使用let关键字而不是var,因此你可以将第一行代码改为let name而不是var name这样:

1
2
3
import UIKit
let name = "Tim McGraw"
name = "Romeo"

但是现在有一个问题:Xcode在第三行旁边显示了一个红色警告符号,它应该在你的代码下方绘制一个弯曲的下划线。如果单击红色警告符号,则Xcode会告诉你问题:“无法分配给’let’值’name’” –这是Xcode所说的“你正在尝试更改常数,而你不能这样做” ”。

因此,常量是向Swift和自己承诺值不会改变的好方法,因为如果你尝试更改它,则Xcode将拒绝运行。Swift开发人员强烈希望尽可能使用常量,因为这样会使你的代码更易于理解。实际上,在最新版本的Swift中,Xcode会告诉你是否将变量设置为变量,然后再不对其进行更改!

重要说明:变量和常量名称在代码中必须唯一。如果你尝试两次使用相同的变量名,则会出现错误,如下所示:

1
2
var name = "Tim McGraw"
var name = "Romeo"

如果操场在你的代码中发现错误,它将在红色框中标记警告,或者只是拒绝运行。你会知道后者是否已发生,因为结果窗格中的文本变为灰色而不是通常的黑色。

类型

数据种类繁多,Swift会单独处理它们。在将一些文本分配给变量时,你已经看到了最重要的类型之一,但是在Swift中,这被称为a String–实际上是一个字符串。

字符串可以是长字符串(例如一百万个字母或更多),短字符串(例如10个字母)甚至是空字符串(无字母),这无关紧要:在Swift的眼中,它们都是字符串,并且它们的工作原理相同。Swift知道name应该包含一个字符串,因为在创建字符串时会为其分配一个字符串:“ Tim McGraw”。如果你要以此重写代码,它将停止工作:

1
2
var name
name = "Tim McGraw"

这次Xcode将为你提供一条错误消息,该错误消息现在还没有多大意义:“模式中缺少类型注释”。意思是,“ name由于你没有给我足够的信息,我无法弄清楚数据类型是什么。”

在这一点上,你有两个选择:要么创建变量,然后在一行代码中为其赋予初始值,要么使用所谓的类型注释,在这里你可以告诉Swift变量稍后将保留哪种数据类型,即使你现在没有赋予它任何价值。

你已经了解了第一个选项的外观,因此让我们看第二个选项:键入注释。我们知道这name将是一个字符串,因此我们可以通过写一个then来告诉Swift String,如下所示:

1
2
var name: String
name = "Tim McGraw"

注意:有些人喜欢在冒号前后放置一个空格var name : String,但它们是错误的,你应该避免在礼貌的陪伴中避免提及他们的错误。

这里的教训是,Swift一直想知道每个变量或常量将保存哪种数据类型。总是。你无法逃脱它,这是一件好事,因为它提供了所谓的类型安全性-如果你说“这将容纳一个字符串”,然后再尝试将兔子放在那里,Swift将拒绝。

现在,我们可以通过引入另一个重要的数据类型Int来尝试这种情况,它是“整数”的缩写。整数是整数,例如3、30、300或-16777216。例如:

1
2
3
4
5
var name: String
name = "Tim McGraw"

var age: Int
age = 25

那声明一个变量是一个字符串,一个变量是一个整数。注意如何都String和Int有大写字母在开始,而name并age没有-这是斯威夫特的标准编码约定。编码约定对Swift无关紧要(你可以按自己的喜好写名字!),但对其他开发人员却很重要。在这种情况下,数据类型以大写字母开头,而变量和常量则不是。

现在我们有了两种不同类型的变量,你可以看到实际使用的类型安全性。尝试这样写:

name = 25
age = “Tim McGraw”
在该代码中,你试图将一个整数放入一个字符串变量中,然后将一个字符串放入一个整数变量中,并且值得庆幸的是,Xcode会抛出错误。你可能认为这很花哨,但实际上很有帮助:你保证变量将保存一种特定类型的数据,而Xcode将在整个工作中强制执行该操作。

在继续之前,请删除导致错误的这两行代码,否则你的游乐场将无法正常工作!

浮动和双

让我们看看另外两种数据类型,称为Float和Double。这是Swift用小数部分存储数字的方式,例如3.1、3.141、3.1415926和-16777216.5。有两种数据类型,因为你可以选择所需的精度,但是在大多数情况下并不重要,因此始终使用Apple官方建议,Double因为它具有最高的精度。

尝试将其放入你的游乐场:

1
2
3
4
5
var latitude: Double
latitude = 36.166667

var longitude: Float
longitude = -86.783333

你可以看到两个数字都出现在右侧,但请仔细查看,因为存在微小差异。我们说longitude应该等于-86.783333,但是在结果窗格中,你会看到-86.78333-最后遗漏了最后3个。现在,你可能会说:“朋友之间0.000003有什么关系?” 但这充分证明了我所说的准确性。

由于这些游乐场更新输入文字时,我们可以尝试的东西,所以你可以看到究竟是如何Float与Double不同。尝试将代码更改为:

1
2
3
4
5
6
7
var longitude: Float
longitude = -86.783333
longitude = -186.783333
longitude = -1286.783333
longitude = -12386.783333
longitude = -123486.783333
longitude = -1234586.783333

这是在小数点前增加数字,而在小数点后保持相同的数字。但是,如果你在结果窗格中查看,则会发现在该点之前添加更多数字时,Swift会在其后删除数字。这是因为存储号码的空间有限,因此首先存储最重要的部分–减少1,000,000是一件大事,而减少0.000003则少。

现在尝试将其Float更改为a Double,你将看到Swift每次都会打印出正确的数字:

1
var longitude: Double

这是因为,同样,Double它的精度是的两倍,Float因此不需要削减你的人数即可。但是,双打仍然有限制–如果你尝试使用123456789.123456789这样的庞大数字,你会发现它会减少到123456789.1234568。

布尔型

Swift具有内置的数据类型,可以存储值是true还是false(称为)Bool,它是Boolean的缩写。布尔型没有空间“也许”或“也许”,只有绝对值:是或否。例如:

1
2
3
4
5
6
7
8
var stayOutTooLate: Bool
stayOutTooLate = true

var nothingInBrain: Bool
nothingInBrain = true

var missABeat: Bool
missABeat = false

提示:你会注意到这些变量是以非常特殊的方式编写的:我们没有编写MissABeat,missabeat或其他类似的变体,而是将首字母改为小写,然后将第二个及随后单词的第一个字母大写。之所以称其为“骆驼箱”,是因为它看起来有点像骆驼的驼峰,并且它使读取变量名中的单词变得更加容易。

明智地使用类型注释
如你所知,有两种方法可以告诉Swift变量包含什么类型的数据:在创建变量时分配值,或使用类型注释。如果你有选择的话,第一个总是比较可取的,因为它更清晰。例如:

1
var name = "Tim McGraw"

……优先于:

1
2
var name: String
name = "Tim McGraw"

这适用于所有数据类型。例如:

1
2
3
var age = 25
var longitude = -86.783333
var nothingInBrain = true

这种技术称为类型推断,因为Swift可以通过查看要放入其中的数据类型来推断变量应使用哪种数据类型。当涉及到-86.783333之类的数字时,Swift总是会推断a Double而不是a Float。

为了完整起见,我应该补充一点,可以指定一种数据类型并同时提供一个值,如下所示:

1
var name: String = "Tim McGraw"

运算符

运算符是你在最初的数学课中学到的那些小符号:+加,-减,*乘,/除,=赋值,依此类推。它们都存在于Swift中,还有一些附加功能。

让我们尝试一些基本知识–请在你的游乐场中输入以下内容:

1
2
3
4
var a = 10
a = a + 1
a = a - 1
a = a * a

在结果窗格中,你将分别看到10、11、10和100。现在尝试这个:

1
2
3
var b = 10
b += 10
b -= 10

+=是一个运算符,表示“先添加后赋给”。在我们的例子中,它的意思是“取的当前值b,加上10,然后将结果放回b。” 就像你想象的那样,-=执行相同操作,但是减去而不是添加。因此,该代码将在结果窗格中显示10、20、10。

其中一些运算符适用于其他数据类型。你可能会想到,可以像这样将两个双打加在一起:

1
2
3
var a = 1.1
var b = 2.2
var c = a + b

当涉及到字符串时,+将它们连接在一起。例如:

1
2
3
var name1 = "Tim McGraw"
var name2 = "Romeo"
var both = name1 + " and " + name2

这会将“ Tim McGraw和Romeo”写入结果窗格。

你将看到的另一种常见的运算符称为“模数”,并使用百分号书写:%。这意味着“将左手数除以右数,然后返回余数。”因此,9 % 3返回0,因为3被3除以9,而10 % 3返回1,因为10被3除以3,剩下的为1。

注意:如果你购买了Hacking with Swift,并且在课程中使用了独家指南书,则稍后会发现模数运算符很有用。

比较运算符
Swift有一组用于对值进行比较的运算符。例如:

1
2
3
4
5
6
7
8
var a = 1.1
var b = 2.2
var c = a + b

c > 3
c >= 3
c > 4
c < 4

这表明大于(>),大于或等于(>=)和小于(<)。在结果窗口中,你将看到true,true,false,true –这些是布尔值,因为对每个语句的答案只能是true或false。

如果要检查是否相等,则不能使用=,因为它已经具有含义:用于给变量赋值。因此,Swift具有形式为的替代==,表示“等于”。例如:

1
2
var name = "Tim McGraw"
name == "Tim McGraw"

结果窗格中将显示“ true”。现在,可能会让你感到困惑的是,在Swift字符串中,区分大小写,这意味着“ Tim McGraw”,“ TIM MCGRAW”和“ TiM mCgRaW”被认为是不同的。如果==用于比较两个字符串,则需要确保它们具有相同的字母大小写。

我想向你介绍另一个运算符,它称为“非”运算符:!。是的,这只是一个感叹号。这使你的陈述与所做的相反。例如:

1
2
3
var stayOutTooLate = true
stayOutTooLate
![]tayOutTooLate

这将打印出true,true,false-带有最后一个值,因为它会翻转前一个true。

你也可以使用!with =进行制作!=或“不等于”。例如:

1
2
3
var name = "Tim McGraw"
name == "Tim McGraw"
name != "Tim McGraw"

字符串插值

这实际上是一个非常简单的东西,真是个奇特的名字:在字符串内组合变量和常量。

清除所有你刚刚编写的代码,仅保留以下内容:

1
var name = "Tim McGraw"

如果我们想向用户打印出包含他们姓名的消息,那么字符串内插就是这么简单:你只需编写一个反斜杠,然后是一个开放的括号,然后是你的代码,然后是一个闭合的括号,如下所示:

1
2
var name = "Tim McGraw"
"Your name is \(name)"

结果窗格现在将“你的名字是Tim McGraw”全部显示为一个字符串,因为字符串插值为我们结合了两者。

现在,我们可以使用+运算符编写该代码,如下所示:

1
2
var name = "Tim McGraw"
"Your name is " + name

…但是效率不高,尤其是当你将多个变量组合在一起时。另外,Swift中的字符串插值非常聪明,能够自动处理各种不同的数据类型。例如:

1
2
3
4
5
var name = "Tim McGraw"
var age = 25
var latitude = 36.166667

"Your name is \(name), your age is \(age), and your latitude is \(latitude)"

使用此+方法要困难得多,因为Swift不允许你将整数和双精度数添加到字符串。

此时,你的结果可能不再适合结果窗格,因此请调整窗口大小或将鼠标悬停在结果上,然后单击显示为内联的+按钮。

一个字符串插值的强大功能之间,一切都(和)实际上可以是一个完整的斯威夫特表现。例如,你可以使用运算符在其中进行数学运算,如下所示:

1
2
var age = 25
"You are \(age) years old. In another \(age) years you will be \(age * 2)."

数组

数组使你可以将多个值组合到一个集合中,然后按它们在集合中的位置访问这些值。Swift使用类型推断来找出数组包含的数据类型,如下所示:

1
2
var evenNumbers = [2, 4, 6, 8]
var songs = ["Shake it Off", "You Belong with Me", "Back to December"]

如你所见,Swift使用方括号标记数组的开始和结束,并且数组中的每个项目都用逗号分隔。

当要从数组中读取项目时,有一个陷阱:Swift从0开始计数。这意味着第一个项目为0,第二个项目为1,第三个项目为2,依此类推。尝试将其放入你的游乐场:

1
2
3
4
var songs = ["Shake it Off", "You Belong with Me", "Back to December"]
songs[0]
songs[1]
songs[2]

这将在结果窗格中打印“ Shake it Off”,“ You Belong with Me”和“ Back to December”。

一项在数组中的位置称为其索引,你只需提供其索引就可以从数组中读取任何项。但是,你确实需要小心:我们的数组中包含三项,这意味着索引0、1和2很好用。但是,如果你尝试阅读,songs[3]游乐场将停止工作-如果你在真实的应用中尝试过,它将崩溃!

因为你是通过给它三个字符串来创建数组的,所以Swift知道这是一个字符串数组。你可以通过在操场上使用特殊命令来确认这一点,该命令将打印出任何变量的数据类型,如下所示:

1
2
var songs = ["Shake it Off", "You Belong with Me", "Back to December"]
type(of: songs)

它将打印Array.Type到结果窗格中,告诉你Swift认为songs是字符串数组。

假设你犯了一个错误,并且不小心将数字放在数组的末尾。现在尝试一下,看看结果窗格将显示什么:

1
2
var songs = ["Shake it Off", "You Belong with Me", "Back to December", 3]
type(of: songs)

这次你会看到一个错误。错误不是因为Swift无法处理像这样的混合数组-我将在短时间内向你展示如何做到这一点!–而是因为Swift有所帮助。你将看到的错误消息是:“异构集合文字只能被推断为’[Any]’; 如果有意的话,请添加显式类型注释。”或者用通俗的英语说,“看起来该数组旨在容纳大量数据类型-如果你确实要这样做,请使其明确。”

类型安全性很重要,尽管Swift可以使数组保存任何类型的数据都很整洁,但这种特殊情况是偶然的。幸运的是,我已经说过,你可以使用类型注释来确切指定要存储数组的数据类型。要指定数组的类型,请编写要存储的数据类型,并用括号括起来,如下所示:

1
var songs: [String] = ["Shake it Off", "You Belong with Me", "Back to December", 3]

既然我们已经告诉Swift,我们只想在数组中存储字符串,由于3不是字符串,它将始终拒绝运行代码。

如果你确实希望数组保存任何类型的数据,请使用特殊的Any数据类型,如下所示:

1
var songs: [Any] = ["Shake it Off", "You Belong with Me", "Back to December", 3]

创建数组

如果使用上面显示的语法创建一个数组,Swift将创建该数组并用我们指定的值填充它。如果要创建数组然后在以后填充它,事情就不是那么简单了–这种语法不起作用:

var songs: [String]
songs[0] = “Shake it Off”
原因是乍一看似乎不必要,但具有深层的潜在性能影响,因此恐怕你只能坚持使用它。简而言之,文字var songs: [String]告诉Swift“该songs变量将保存一个字符串数组”,但实际上并没有创建该数组。它不会分配任何RAM,也不会做任何工作来实际创建Swift数组。它只是说在某个时候会有一个数组,它将保存字符串。

有几种方法可以正确地表达这一点,这时可能最有意义的是:

1
var songs: [String] = []

它使用类型注释来明确我们想要一个字符串数组,并为其分配一个空数组(这就是其中的[]一部分)。

你通常还会看到以下结构:

1
var songs = [String]()

这意味着同一件事:()告诉Swift我们要创建有问题的数组,然后songs使用类型推断将其分配给数组。这个选项短了两个字符,所以程序员喜欢它并不奇怪!

数组运算符

你可以在数组上使用一组有限的运算符。例如,你可以使用+运算符合并两个数组,如下所示:

1
2
3
var songs = ["Shake it Off", "You Belong with Me", "Love Story"]
var songs2 = ["Today was a Fairytale", "Welcome to New York", "Fifteen"]
var both = songs + songs2

你也可以使用+ =进行添加和分配,如下所示:

1
both += ["Everything has Changed"]

字典

如你所见,Swift数组是一个集合,你可以在其中使用数字索引(例如)访问每个项目songs[0]。字典是集合的另一种常见类型,但是它们与数组不同,因为它们使你可以根据指定的键访问值。

举个例子,让我们想象一下如何将一个人的数据存储在一个数组中:

1
var person = ["Taylor", "Alison", "Swift", "December", "taylorswift.com"]

我们将使用读出该人的中间名,person[1]并使用读出他们的出生月份person[3]。这有一些问题,尤其是很难记住为数组中的每个值分配了什么索引号!如果该人没有中间名怎么办?可能所有其他值都向下移动一位,从而导致代码混乱。

使用字典,我们可以将其重写为更明智的方法,因为你可以使用指定的键来读写值,而不是任意的数字。例如:

1
2
3
var person = ["first": "Taylor", "middle": "Alison", "last": "Swift", "month": "December", "website": "taylorswift.com"]
person["middle"]
person["month"]

如果我使用大量的空白来拆分屏幕上的字典,可能会有所帮助,如下所示:

1
2
3
4
5
6
7
8
9
10
var person = [
"first": "Taylor",
"middle": "Alison",
"last": "Swift",
"month": "December",
"website": "taylorswift.com"
]

person["middle"]
person["month"]

如你所见,当你制作字典时,你要写它的键,然后是冒号,然后是值。然后,你只需知道其键即可从字典中读取任何值,这更容易使用。

与数组一样,你可以在字典中存储各种值,尽管键通常是字符串。

条件语句

有时,你希望代码仅在满足特定条件的情况下才执行,而在Swift中主要由ifand else语句表示。给Swift一个条件检查,然后在条件为真的情况下执行一段代码。

else如果条件为假,甚至else if还有更多条件,你还可以选择编写并提供代码块来执行。代码的“块”只是一小段代码,{在其开头标记为大括号},在其结尾标记为大括号。

这是一个基本示例:

1
2
3
4
5
6
var action: String
var person = "hater"

if person == "hater" {
action = "hate"
}

它使用==前面介绍的(相等)运算符来检查其中的字符串person是否完全等同于字符串“ hater”。如果是,它将action变量设置为“讨厌”。请注意,打开括号和闭合括号也因其不太专业的名称“花括号”而闻名–标记了条件为真时将要执行的代码的开始和结束。

让我们添加else if和else阻止:

1
2
3
4
5
6
7
8
9
10
var action: String
var person = "hater"

if person == "hater" {
action = "hate"
} else if person == "player" {
action = "play"
} else {
action = "cruise"
}

这将按顺序检查每个条件,并且只会执行其中一个块:一个人是仇恨者,玩家或其他任何人。

评估多个条件

你可以要求Swift评估任意多个条件,但是为了使Swift执行代码块,所有条件都必须为真。要检查多个条件,请使用&&运算符-表示“和”。例如:

1
2
3
4
5
6
7
var action: String
var stayOutTooLate = true
var nothingInBrain = true

if stayOutTooLate && nothingInBrain {
action = "cruise"
}

因为stayOutTooLate和nothingInBrain都为真,所以整个条件为真,并action设置为“巡航”。Swift使用一种称为“短路评估”的方法来提高性能:如果它正在评估多个都必须为真的事物,而第一个为假,那么它甚至不会理会其余的事物。

寻找真理的反面

这听起来可能具有深刻的哲学意义,但实际上这很重要:有时你会在乎条件是否不正确,即是否错误。你可以使用!前面介绍的(非)运算符进行此操作。例如:

1
2
3
if ![]tayOutTooLate && !nothingInBrain {
action = "cruise"
}

这一次,action变量将仅在两个设置stayOutTooLate和nothingInBrain是假的-在!已经围绕翻转他们。

循环

在你花很长时间阅读完这句话之后,计算机非常擅长执行无聊的任务。在代码中重复执行任务时,你可以复制和粘贴代码多次,也可以使用循环 -只要条件为真,重复执行一段代码的简单编程结构。

为了说明这一点,我想向你介绍一个特殊的调试功能print()::给它一些文本进行打印,然后它将进行打印。如果你像我们一样在操场上跑步,你会看到文本出现在结果窗口中。如果你在Xcode中运行真实的应用程序,则会在Xcode的日志窗口中看到你的文本。无论哪种方式,print()都是偷看变量内容的好方法。

看一下这段代码:

1
2
3
4
5
6
7
8
9
10
print("1 x 10 is \(1 * 10)")
print("2 x 10 is \(2 * 10)")
print("3 x 10 is \(3 * 10)")
print("4 x 10 is \(4 * 10)")
print("5 x 10 is \(5 * 10)")
print("6 x 10 is \(6 * 10)")
print("7 x 10 is \(7 * 10)")
print("8 x 10 is \(8 * 10)")
print("9 x 10 is \(9 * 10)")
print("10 x 10 is \(10 * 10)")

完成运行后,你的Playground结果窗格中将具有10 times表。但这不是高效的代码,实际上,更干净的方法是使用封闭范围运算符(连续三个句点)循环遍历一系列数字:…

使用封闭范围运算符,我们可以用三行代码重写整个过程:

1
2
3
for i in 1...10 {
print("\(i) x 10 is \(i * 10)")
}

结果窗格的循环仅显示“(10次)”,这意味着循环已运行10次。如果你想知道循环的实际作用,请立即单击“(10次)”右侧的方框。你会在代码内看到一个框,上面写着“ 10 x 10是100”,如果你右键单击该框,应该会看到“值历史记录”选项。现在单击它,你应该看到下面的图片:

循环的作用是从1到10(包括1和10)计数,将该数字分配给常量i,然后在花括号内运行代码块。

如果你不需要知道自己的电话号码,可以改用下划线。例如,我们可以像这样打印一些Taylor Swift的歌词:

1
2
3
4
5
6
7
var str = "Fakers gonna"

for _ in 1 ... 5 {
str += " fake"
}

print(str)

每次循环运行时,将在字符串中添加“ Fakers假货假货假货假货”。

如果Swift不必在每次循环时都将每个数字分配给一个变量,那么它可以更快地运行你的代码。结果,如果你编写for i in…然后不使用i,则Xcode建议你将其更改为_。

有一个封闭范围运算符的变体,称为半开范围运算符,它们很容易混淆。半开范围运算符的外观..<和计数范围从一个数字到另一个数字(不包括另一个数字)。例如,1 ..< 5将计数1、2、3、4。

遍历数组

Swift提供了一种非常简单的方法来遍历数组中的所有元素。由于Swift已经知道你的数组保存的数据类型,因此它将遍历数组中的每个元素,将其分配给你命名的常量,然后运行代码块。例如,我们可以打印出一些很棒的歌曲,如下所示:

1
2
3
4
5
var songs = ["Shake it Off", "You Belong with Me", "Look What You Made Me Do"]

for song in songs {
print("My favorite song is \(song)")
}

你还可以使用for i in循环构造来遍历数组,因为你可以使用该常数来索引数组。我们甚至可以使用它来索引成两个数组,如下所示:

1
2
3
4
5
6
var people = ["players", "haters", "heart-breakers", "fakers"]
var actions = ["play", "hate", "break", "fake"]

for i in 0 ... 3 {
print("\(people[i]) gonna \(actions[i])")
}

你可能想知道半开范围运算符有什么用,但是由于数组从零开始计数,所以对数组的使用特别有用。因此,我们可以从0到不包括3的数量进行计数,而不是从0到3(包括3)的数量进行计数。

请记住:它们从零开始计数,因此,如果它们有4个项目,则最大索引为3,这就是为什么我们需要在循环中使用“ 排除 ”的原因。

要计算数组中有多少项,请使用someArray.count。因此,我们可以这样重写代码:

1
2
3
4
5
6
var people = ["players", "haters", "heart-breakers", "fakers"]
var actions = ["play", "hate", "break", "fake"]

for i in 0 ..< people.count {
print("\(people[i]) gonna \(actions[i])")
}

内循环

你可以根据需要将循环放在循环内,甚至可以将循环放在循环内—尽管你可能突然发现自己在做一千万次,所以要小心!

我们可以结合之前的两个循环来创建此循环:

1
2
3
4
5
6
7
8
9
10
11
12
var people = ["players", "haters", "heart-breakers", "fakers"]
var actions = ["play", "hate", "break", "fake"]

for i in 0 ..< people.count {
var str = "\(people[i]) gonna"

for _ in 1 ... 5 {
str += " \(actions[i])"
}

print(str)
}

输出“播放器播放器播放器播放器”,然后输出“讨厌者播放器…”。

重要提示:尽管程序员通常使用i,j甚至k对于循环常量,也可以随意命名:这for personNumber in 0 ..< people.count是完全有效的。

While循环

你将看到第三种循环,该循环重复一段代码,直到你告诉它停止为止。这用于诸如游戏循环之类的事情,在这种情况下,你事先不知道游戏将持续多长时间–你只需重复“检查触摸,为机器人动画,绘制屏幕,​​检查触摸……”等等,直到最终用户点击一个按钮退出游戏并返回主菜单。

这些循环称为while循环,它们看起来像这样:

1
2
3
4
5
6
7
8
9
10
var counter = 0

while true {
print("Counter is now \(counter)")
counter += 1

if counter == 556 {
break
}
}

该代码引入了一个名为的新关键字break。它用于在你决定的点退出while或for循环。没有它,上面的代码将永远不会结束,因为要检查的条件仅仅是“ true”,而true始终是true。没有该break语句,循环是无限循环,这是一件坏事。

while当你使用未知数据时,例如从Internet下载内容,从XML之类的文件中进行读取,查看用户输入等,这些循环最有效。这是因为只有运行了足够多次后,你才知道何时停止循环。

有一个对口break叫continue。退出循环会立即停止执行并在循环后立即继续,而继续循环只会退出循环的当前迭代-它会跳回到循环的顶部并从那里开始。

例如,请考虑以下代码:

1
2
3
4
5
6
7
8
9
var songs = ["Shake it Off", "You Belong with Me", "Look What You Made Me Do"]

for song in songs {
if song == "You Belong with Me" {
continue
}

print("My favorite song is \(song)")
}

循环播放三首泰勒·斯威夫特的歌曲,但只会显示两首的名字。这样做的原因是continue关键字:当循环尝试使用歌曲“ You Belong with Me”时,continue会被调用,这意味着循环会立即跳回开始位置- print()永远不会进行调用,而是循环继续进行“看看你让我做什么”。

案例

你已经看到了if语句,现在开始循环,但是Swift拥有另一种称为的流控制switch/case。最容易想到的是,它是的高级形式if,因为你可以进行很多匹配,而Swift会执行正确的匹配。

以最基本的形式,switch/case你告诉Swift你要检查的变量,然后提供该变量的可能情况列表。Swift将查找与你的变量匹配的第一种情况,然后运行其代码块。该块结束时,Swift退出整个switch/case块。

这是一个基本示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
let liveAlbums = 2

switch liveAlbums {
case 0:
print("You're just starting out")

case 1:
print("You just released iTunes Live From SoHo")

case 2:
print("You just released Speak Now World Tour")

default:
print("Have you done something new?")
}

我们可能已经写了很多使用ifand else if块的方法,但是这种方法更清晰,这很重要。

switch/caseSwift的优点之一是可以确保你的案件详尽无遗。就是说,如果你的变量可能有一个你不检查的值,那么Xcode将拒绝构建你的应用程序。

在值实际上是开放式的情况下,例如我们的liveAlbums整数,你需要包含一个default案例以捕获这些潜在值。是的,即使你“知道”你的数据只能落在一定范围内,Swift也要绝对确定。

Swift可以对你的case语句应用一些求值以便与变量匹配。例如,如果要检查可能值的范围,则可以使用封闭范围运算符,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
let studioAlbums = 5

switch studioAlbums {
case 0...1:
print("You're just starting out")

case 2...3:
print("You're a rising star")

case 4...5:
print("You're world famous!")

default:
print("Have you done something new?")
}

你应该知道的一件事是,switch/caseSwift 中的块不会像你在其他语言中看到的那样掉入。如果你已经习惯了写break在你的case街区,你应该知道这是没有必要的斯威夫特。

而是使用fallthrough关键字使一种情况落入另一种情况–实际上是相反的。当然,如果你不知道这意味着什么,那就更好了:不用担心!

参考资料

查看下一天的SwiftUI学习笔记

关于100days英文课程