基础知识
Swift 是一种用于 iOS、macOS、watchOS 和 tvOS 应用程序开发的新编程语言。尽管如此,根据您使用 C 和 Objective-C 进行开发的经验,您将熟悉 Swift 的许多部分。
雨燕提供了自己的所有基本C和Objective-C类型的版本,包括Int为整数,Double并Float为浮点值,Bool布尔值,并String为文本数据。Swift 还提供了三种主要集合类型Array、Set、 和 的强大版本Dictionary,如集合类型 中所述。
与 C 一样,Swift 使用变量来存储和通过标识名称引用值。Swift 还广泛使用了无法更改其值的变量。这些被称为常量,并且比 C 中的常量强大得多。当您使用不需要更改的值时,常量在整个 Swift 中使用以使代码更安全、更清晰。
除了熟悉的类型之外,Swift 还引入了 Objective-C 中没有的高级类型,例如元组。元组使您能够创建和传递值的分组。您可以使用元组将函数中的多个值作为单个复合值返回。
Swift 还引入了可选类型,用于处理没有值的情况。选配说要么“有是一个值,它等于X ”或“有没有一个价值可言”。使用可选项类似于nil在 Objective-C 中使用指针,但它们适用于任何类型,而不仅仅是类。可选项不仅比nilObjective-C 中的指针更安全和更具表现力,而且它们是 Swift 中许多最强大功能的核心。
Swift 是一种类型安全的语言,这意味着该语言可以帮助您明确代码可以使用的值的类型。如果您的代码的一部分需要String,类型安全可以防止您Int错误地传递它。同样,类型安全可防止您意外地将 optional 传递String给需要非可选String. 类型安全可帮助您在开发过程中尽早发现和修复错误。
常量和变量
常量和变量将名称(例如maximumNumberOfLoginAttempts或welcomeMessage)与特定类型的值(例如数字10或字符串"Hello")相关联。常量的值一旦设置就不能更改,而变量可以在将来设置为不同的值。
声明常量和变量
常量和变量必须在使用前声明。用let关键字声明常量,用关键字声明变量var。下面是一个示例,说明如何使用常量和变量来跟踪用户进行的登录尝试次数:
-
1. let maximumNumberOfLoginAttempts = 10
2. var currentLoginAttempt = 0
这段代码可以读作:
“声明一个名为 的新常量maximumNumberOfLoginAttempts,并赋予它一个值10。然后,声明一个名为 的新变量currentLoginAttempt,并为其赋予初始值0。”
在此示例中,允许的最大登录尝试次数声明为常量,因为最大值永远不会改变。当前登录尝试计数器被声明为一个变量,因为该值必须在每次登录尝试失败后递增。
您可以在一行中声明多个常量或多个变量,用逗号分隔:
-
var x = 0.0, y = 0.0, z = 0.0
笔记
如果代码中存储的值不会更改,请始终使用let关键字将其声明为常量。变量仅用于存储需要能够更改的值。
类型注释
您可以在声明常量或变量时提供类型注释,以明确常量或变量可以存储的值类型。通过在常量或变量名称之后放置一个冒号,然后是一个空格,然后是要使用的类型的名称来编写类型注释。
此示例为名为 的变量提供了类型注释welcomeMessage,以指示该变量可以存储String值:
- var welcomeMessage: String
声明中的冒号表示“……类型……”,因此上面的代码可以理解为:
“声明一个welcomeMessage类型为 的变量String。”
短语“of type String”的意思是“可以存储任何String值”。将其视为可以存储的“事物的类型”(或“事物的种类”)。
welcomeMessage现在可以将该变量设置为任何字符串值而不会出错:
- welcomeMessage = “Hello”
您可以在一行中定义多个相同类型的相关变量,以逗号分隔,并在最终变量名称后使用单个类型注释:
- var red, green, blue: Double
笔记
在实践中很少需要编写类型注释。如果您在定义常量或变量时为其提供初始值,Swift 几乎总能推断出要用于该常量或变量的类型,如类型安全和类型推断中所述。在welcomeMessage上面的例子中,没有提供初始值,所以welcomeMessage变量的类型是用类型注释指定的,而不是从初始值推断出来的。
命名常量和变量
常量和变量名称几乎可以包含任何字符,包括 Unicode 字符:
- let π = 3.14159
- let 你好 = “你好世界”
- let 🐶🐮 = “dogcow”
常量和变量名称不能包含空格字符、数学符号、箭头、专用 Unicode 标量值或线条和方框图字符。它们也不能以数字开头,尽管数字可能包含在名称的其他地方。
一旦声明了某个类型的常量或变量,就不能再用相同的名称声明它,也不能将其更改为存储不同类型的值。你也不能把一个常数变成一个变量或一个变量变成一个常数。
笔记
如果您需要为常量或变量赋予与 Swift 保留关键字相同的名称,请```在将其用作名称时用反引号 ( )将关键字括起来。但是,除非您绝对别无选择,否则请避免使用关键字作为名称。
您可以将现有变量的值更改为兼容类型的另一个值。在本例中, 的值friendlyWelcome从 更改"Hello!"为"Bonjour!":
-
1. var friendlyWelcome = "Hello!"
2. friendlyWelcome = "Bonjour!"
3.
与变量不同,常量的值在设置后不能更改。尝试这样做会在编译代码时报告为错误:
-
1. let languageName = "Swift"
2. languageName = "Swift++"
3.
打印常量和变量
您可以使用以下print(_:separator:terminator:)函数打印常量或变量的当前值:
-
1. print(friendlyWelcome)
2.
该print(_:separator:terminator:)函数是一个全局函数,可将一个或多个值打印到适当的输出。例如,在 Xcode 中,该print(_:separator:terminator:)函数在 Xcode 的“控制台”窗格中打印其输出。该separator和terminator参数都有默认值,这样你就可以当你调用这个函数忽略它们。默认情况下,该函数通过添加换行符来终止它打印的行。要打印一个没有换行符的值,请传递一个空字符串作为终止符——例如,. 有关具有默认值的参数的信息,请参阅默认参数值。print(someValue, terminator: "")
Swift 使用字符串插值将常量或变量的名称作为占位符包含在较长的字符串中,并提示 Swift 将其替换为该常量或变量的当前值。将名称括在括号中,并在左括号前用反斜杠将其转义:
-
1. print("The current value of friendlyWelcome is \(friendlyWelcome)")
2.
笔记
你可以用串插中使用的所有选项中描述字符串插值。
注释
使用注释在代码中包含不可执行的文本,作为对自己的注释或提醒。编译代码时,Swift 编译器会忽略注释。
Swift 中的注释与 C 中的注释非常相似。单行注释以两个正斜杠 ( //)开头:
-
// This is a comment.
多行注释以正斜杠开头,后跟星号 ( /*),以星号结尾,后跟正斜杠 ( */):
-
/* This is also a comment
but is written over multiple lines. */
与 C 中的多行注释不同,Swift 中的多行注释可以嵌套在其他多行注释中。您可以通过启动一个多行注释块然后在第一个块中启动第二个多行注释来编写嵌套注释。然后关闭第二个块,然后关闭第一个块:
-
/* This is the start of the first multiline comment.
/* This is the second, nested multiline comment. */
This is the end of the first multiline comment. */
嵌套的多行注释使您能够快速轻松地注释掉大块代码,即使代码已经包含多行注释。
分号
与许多其他语言不同,Swift 不要求您;在代码中的每个语句之后编写分号 ( ),尽管您可以根据需要这样做。但是,如果要在一行中编写多个单独的语句,则需要分号:
-
1. let cat = "🐱"; print(cat)
2.
整数
整数是没有小数部分的整数,例如42和-23。整数有符号(正、零或负)或无符号(正或零)。
Swift 提供 8、16、32 和 64 位形式的有符号和无符号整数。这些整数遵循类似于 C 的命名约定,其中 8 位无符号整数的类型为UInt8,而 32 位有符号整数的类型为Int32。与 Swift 中的所有类型一样,这些整数类型的名称大写。
整数边界
您可以使用其min和max属性访问每个整数类型的最小值和最大值:
-
1. let minValue = UInt8.min
2. let maxValue = UInt8.max
这些属性的值是适当大小的数字类型(例如UInt8在上面的示例中),因此可以在表达式中与相同类型的其他值一起使用。
整数
在大多数情况下,您不需要选择特定大小的整数来在您的代码中使用。Swift 提供了一个额外的整数类型,Int,它的大小与当前平台的原生字大小相同:
- 在 32 位平台上,
Int与Int32. - 在 64 位平台上,
Int与Int64.
除非您需要使用特定大小的整数,否则请始终Int在代码中使用整数值。这有助于代码一致性和互操作性。即使在 32 位平台上,Int也可以存储-2,147,483,648和之间的任何值2,147,483,647,并且对于许多整数范围来说都足够大。
用户界面
Swift 还提供了一个无符号整数类型,UInt它的大小与当前平台的原生字大小相同:
- 在 32 位平台上,
UInt与UInt32. - 在 64 位平台上,
UInt与UInt64.
笔记
UInt仅当您特别需要与平台的本机字大小相同大小的无符号整数类型时才使用。如果不是这种情况,Int则是首选,即使要存储的值已知为非负值也是如此。一致使用Intfor 整数值有助于代码互操作性,避免在不同数字类型之间进行转换的需要,并匹配整数类型推断,如类型安全和类型推断中所述。
浮点数字
浮点数是具有小数部分的数字,例如3.14159,0.1,和-273.15。
浮点类型可以表示比整数类型更广泛的值,并且可以存储比Int. Swift 提供了两种有符号浮点数类型:
Double 表示 64 位浮点数。Float 表示一个 32 位浮点数。
笔记
Double具有至少 15 位十进制数字的精度,而 的精度Float可以低至 6 位十进制数字。要使用的适当浮点类型取决于您需要在代码中使用的值的性质和范围。在任何一种类型都合适的情况下,Double是首选。
类型安全和类型推断
Swift 是一种类型安全的语言。类型安全语言鼓励您明确代码可以使用的值类型。如果您的代码的一部分需要String,则不能Int错误地传递它。
因为 Swift 是类型安全的,所以它在编译代码时会执行类型检查,并将任何不匹配的类型标记为错误。这使您能够在开发过程中尽早发现和修复错误。
类型检查可帮助您在处理不同类型的值时避免错误。但是,这并不意味着您必须指定您声明的每个常量和变量的类型。如果你没有指定你需要的值的类型,Swift 会使用类型推断来计算出合适的类型。类型推断使编译器能够在编译您的代码时自动推断特定表达式的类型,只需检查您提供的值即可。
由于类型推断,Swift 需要的类型声明比 C 或 Objective-C 等语言少得多。常量和变量仍然是显式类型的,但是指定它们的类型的大部分工作已经为您完成了。
当您使用初始值声明常量或变量时,类型推断特别有用。这通常是通过在您声明常量或变量时为常量或变量分配一个文字值(或文字)来完成的。(文字值是直接出现在源代码中的值,如下面的42和3.14159示例中所示。)
例如,如果你将一个字面值 of 赋给一个42新常量而没有说明它是什么类型,Swift 会推断你希望这个常量是 an Int,因为你已经用一个看起来像整数的数字来初始化它:
-
1. let meaningOfLife = 42
2.
同样,如果您没有为浮点文字指定类型,Swift 会推断您要创建一个Double:
-
1. let pi = 3.14159
2.
Swift在推断浮点数的类型时总是选择Double(而不是Float)。
如果在表达式中组合整数和浮点文字,Double将从上下文推断出一种类型:
-
1. let anotherPi = 3 + 0.14159
2.
的字面值3本身没有显式类型,因此Double从作为加法一部分的浮点字面量的存在推断出适当的输出类型。
数字文字
整数文字可以写成:
- 一个十进制数,没有前缀
- 一个二进制数,有
0b前缀 - 一个八进制数,带
0o前缀 - 一个十六进制数,有
0x前缀
所有这些整数文字的十进制值为17:
-
1. let decimalInteger = 17
2. let binaryInteger = 0b10001
3. let octalInteger = 0o21
4. let hexadecimalInteger = 0x11
浮点文字可以是十进制(没有前缀)或十六进制(有0x前缀)。它们的小数点两侧必须始终有一个数字(或十六进制数)。十进制浮点数也可以有一个可选的指数,由大写或小写表示e;十六进制浮点数必须有一个指数,由大写或小写表示p。
对于指数为 的十进制数exp,基数乘以 10 exp:
1.25e2表示 1.25 x 10 2,或125.0。1.25e-2表示 1.25 x 10 -2,或0.0125。
对于指数为 的十六进制数exp,基数乘以 2 exp:
0xFp2表示 15 x 2 2,或60.0。0xFp-2表示 15 x 2 -2,或3.75。
所有这些浮点文字的十进制值为12.1875:
-
1. let decimalDouble = 12.1875
2. let exponentDouble = 1.21875e1
3. let hexadecimalDouble = 0xC.3p0
数字文字可以包含额外的格式以使其更易于阅读。整数和浮点数都可以用额外的零填充,并且可以包含下划线以提高可读性。两种格式都不会影响文字的基础值:
-
1. let paddedDouble = 000123.456
2. let oneMillion = 1_000_000
3. let justOverOneMillion = 1_000_000.000_000_1
数字类型转换
Int对代码中的所有通用整数常量和变量使用该类型,即使它们是非负的。在日常情况下使用默认整数类型意味着整数常量和变量可以立即在您的代码中互操作,并将匹配整数文字值的推断类型。
仅当手头的任务特别需要其他整数类型时才使用其他整数类型,因为来自外部源的明确大小的数据,或者为了性能、内存使用或其他必要的优化。在这些情况下使用显式大小的类型有助于捕获任何意外的值溢出并隐式记录正在使用的数据的性质。
整数转换
可以存储在整数常量或变量中的数字范围因每种数字类型而异。一个Int8常数或变量可以存储之间的数字-128和127,而UInt8常数或变量可以存储之间的数字0和255。编译代码时,将不适合大小整数类型的常量或变量的数字报告为错误:
-
1. let cannotBeNegative: UInt8 = -1
2.
3. let tooBig: Int8 = Int8.max + 1
4.
5.
由于每种数字类型可以存储不同范围的值,因此您必须根据具体情况选择数字类型转换。这种选择加入的方法可以防止隐藏的转换错误,并有助于在您的代码中明确类型转换意图。
要将一种特定的数字类型转换为另一种,请使用现有值初始化所需类型的新数字。在下面的示例中,常量twoThousand的类型为UInt16,而常量one的类型为UInt8。它们不能直接相加,因为它们的类型不同。相反,此示例调用UInt16(one)创建一个UInt16使用 值初始化的新值one,并使用此值代替原始值:
-
1. let twoThousand: UInt16 = 2_000
2. let one: UInt8 = 1
3. let twoThousandAndOne = twoThousand + UInt16(one)
因为加法的两边现在都是 type UInt16,所以加法是允许的。输出常量 ( twoThousandAndOne) 被推断为类型UInt16,因为它是两个UInt16值的总和。
SomeType(ofInitialValue)是调用 Swift 类型的初始值设定项并传入初始值的默认方式。在幕后,UInt16有一个接受UInt8值的初始化器,因此这个初始化器用于UInt16从现有的UInt8. 但是,您不能在此处传入任何类型——它必须是UInt16提供初始化程序的类型。Extensions 中介绍了扩展现有类型以提供接受新类型(包括您自己的类型定义)的初始值设定项。
整数和浮点转换
整数和浮点数值类型之间的转换必须明确:
-
1. let three = 3
2. let pointOneFourOneFiveNine = 0.14159
3. let pi = Double(three) + pointOneFourOneFiveNine
4.
在这里,常量的值three用于创建一个新的 type 值Double,这样加法的两边都是相同的类型。如果没有这种转换,将不允许添加。
浮点到整数的转换也必须明确。整数类型可以用 aDouble或Float值初始化:
-
1. let integerPi = Int(pi)
2.
当以这种方式初始化一个新的整数值时,浮点值总是被截断。这意味着4.75成为4和-3.9成为-3。
笔记
数字常量和变量的组合规则与数字文字的规则不同。文字值3可以直接添加到文字 value 0.14159,因为数字文字本身没有显式类型。它们的类型仅在编译器评估它们时推断出来。
类型别名
类型别名定义现有类型的替代名称。您可以使用typealias关键字定义类型别名。
当您想通过上下文更合适的名称引用现有类型时,类型别名很有用,例如处理来自外部源的特定大小的数据时:
-
typealias AudioSample = UInt16
一旦定义了类型别名,就可以在任何可能使用原始名称的地方使用别名:
-
1. var maxAmplitudeFound = AudioSample.min
2.
此处,AudioSample定义为 的别名UInt16。因为它是一个别名,调用AudioSample.min实际调用UInt16.min,它提供的初始值0的maxAmplitudeFound变量。
布尔值
Swift 有一个基本的布尔类型,称为Bool. 布尔值被称为逻辑值,因为它们只能为真或假。Swift 提供了两个布尔常量值,true以及false:
-
1. let orangesAreOrange = true
2. let turnipsAreDelicious = false
该类型的orangesAreOrange和turnipsAreDelicious被推断为Bool一个事实,即他们与布尔文字值初始化。正如Int和Double上面,你并不需要声明常量或变量Bool,如果将其设置为true或者false只要你创建它们。当使用类型已知的其他值初始化常量或变量时,类型推断有助于使 Swift 代码更加简洁和可读。
当您使用条件语句时,布尔值特别有用,例如if:
-
1. if turnipsAreDelicious {
2. ? print("Mmm, tasty turnips!")
3. } else {
4. ? print("Eww, turnips are horrible.")
5. }
6.
控制流if中更详细地介绍了条件语句(例如语句)。
Swift 的类型安全性防止非布尔值被替换为Bool. 以下示例报告编译时错误:
-
1. let i = 1
2. if i {
3. ?
4. }
但是,下面的替代示例是有效的:
-
1. let i = 1
2. if i == 1 {
3. ?
4. }
比较的结果是 type ,因此第二个示例通过了类型检查。基本运算符中讨论了类似的比较。i == 1``Bool``i == 1
与 Swift 中的其他类型安全示例一样,这种方法避免了意外错误并确保特定代码段的意图始终清晰。
元组
元组将多个值分组为一个复合值。元组中的值可以是任何类型,并且不必彼此具有相同的类型。
在本例中,是一个描述HTTP 状态代码的元组。HTTP 状态代码是在您请求网页时由 Web 服务器返回的特殊值。如果您请求的网页不存在,则返回状态代码。(404, "Not Found")``404 Not Found
-
1. let http404Error = (404, "Not Found")
2.
的元组基团一起的和,得到的HTTP状态代码两个独立的值:一个数字和一个人类可读的描述。它可以被描述为“类型的元组”。(404, "Not Found")``Int``String``(Int, String)
您可以从任何类型的排列中创建元组,并且它们可以包含任意数量的不同类型。没有什么可以阻止您拥有类型为、 或的元组,或者实际上是您需要的任何其他排列。(Int, Int, Int)``(String, Bool)
您可以将元组的内容分解为单独的常量或变量,然后您可以像往常一样访问它们:
-
1. let (statusCode, statusMessage) = http404Error
2. print("The status code is \(statusCode)")
3.
4. print("The status message is \(statusMessage)")
5.
如果您只需要元组的某些值,请_在分解元组时忽略带有下划线 ( ) 的部分元组:
-
1. let (justTheStatusCode, _) = http404Error
2. print("The status code is \(justTheStatusCode)")
3.
或者,使用从零开始的索引号访问元组中的各个元素值:
-
1. print("The status code is \(http404Error.0)")
2.
3. print("The status message is \(http404Error.1)")
4.
您可以在定义元组时命名元组中的各个元素:
-
let http200Status = (statusCode: 200, description: "OK")
如果在元组中命名元素,则可以使用元素名称访问这些元素的值:
-
1. print("The status code is \(http200Status.statusCode)")
2.
3. print("The status message is \(http200Status.description)")
4.
元组作为函数的返回值特别有用。尝试检索网页的函数可能会返回元组类型来描述页面检索的成功或失败。通过返回一个具有两个不同值的元组,每个值都是不同的类型,与只能返回单一类型的单个值相比,该函数提供了更多关于其结果的有用信息。有关更多信息,请参阅具有多个返回值的函数。(Int, String)
笔记
元组对于简单的相关值组很有用。它们不适合创建复杂的数据结构。如果您的数据结构可能更复杂,请将其建模为类或结构,而不是元组。有关更多信息,请参阅结构和类。
-------持续更新---------
|