★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★ ➤微信公众号:山青咏芝(shanqingyongzhi) ➤博客园地址:山青咏芝(https://www.cnblogs.com/strengthen/) ➤GitHub地址:https://github.com/strengthen/LeetCode ➤原文地址:https://www.cnblogs.com/strengthen/p/9711776.html ➤如果链接不是山青咏芝的博客园地址,则可能是爬取作者的文章。 ➤原文已修改更新!强烈建议点击原文地址阅读!支持作者!支持原创! ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
热烈欢迎,请直接点击!!!
进入博主App Store主页,下载使用各个作品!!!
注:博主将坚持每月上线一个新app!!!
Swift是一种用于iOS,macOS,watchOS和tvOS应用程序开发的新编程语言。尽管如此,从您使用C和Objective-C进行开发的经验中,Swift的许多部分将为您所熟悉。
雨燕提供了自己的所有基本C和Objective-C类型的版本,包括Int 为整数,Double 并Float 为浮点值,Bool 布尔值,并String 为文本数据。雨燕还提供了三种主要类型的集合强大的版本Array ,Set 和Dictionary ,如在集合类型。
与C一样,Swift使用变量来存储和通过标识名称引用值。Swift还广泛使用了无法更改其值的变量。这些被称为常量,并且比C中的常量功能强大得多。在整个Swift中使用常量可以使代码在使用不需要更改的值时更安全,更清晰。
除了熟悉的类型外,Swift还引入了在Objective-C中找不到的高级类型,例如元组。元组使您可以创建和传递值分组。您可以使用元组从一个函数返回多个值作为单个复合值。
Swift还引入了可选类型,用于处理缺少值的情况。选配说要么“有是一个值,它等于X ”或“有没有一个价值可言”。nil 在Objective-C中,使用可选参数与使用指针相似,但是它们适用于任何类型,而不仅仅是类。可选控件不仅比nil Objective-C中的指针更安全,更富有表现力,而且它们是Swift最强大的功能的核心。
Swift是一种类型安全的语言,这意味着该语言可帮助您弄清代码可以使用的值的类型。如果代码的一部分需要使用String ,则类型安全性可防止您Int 误将其传递。同样,类型安全性可以防止您意外地将可选参数传递String 给需要非可选参数的代码String 。类型安全性可帮助您在开发过程中尽早发现并修复错误。
常量和变量
常量和变量将名称(例如maximumNumberOfLoginAttempts 或welcomeMessage )与特定类型的值(例如数字10 或字符串"Hello" )相关联。常量的值一旦设置就无法更改,而将来可以将变量设置为其他值。
声明常量和变量
常量和变量必须在使用前声明。您可以使用let 关键字声明常量,并使用关键字声明变量var 。这是一个示例,说明如何使用常量和变量来跟踪用户进行的登录尝试次数:
- let maximumNumberOfLoginAttempts = 10
- var currentLoginAttempt = 0
此代码可以读取为:
“声明一个名为的新常数maximumNumberOfLoginAttempts ,并为其赋予值10 。然后,声明一个名为的新变量currentLoginAttempt ,并将其初始值赋予0 。”
在此示例中,将允许的最大登录尝试次数声明为一个常数,因为最大值不会更改。当前的登录尝试计数器被声明为变量,因为在每次失败的登录尝试之后都必须将该值递增。
您可以在一行中声明多个常量或多个变量,并用逗号分隔:
- var x = 0.0, y = 0.0, z = 0.0
笔记
如果代码中的存储值不变,请始终使用let 关键字将其声明为常量。仅将变量用于存储需要更改的值。
类型注释
声明常量或变量时,可以提供类型注释,以明确常量或变量可以存储的值的类型。通过在常量或变量名称后加冒号,后跟空格,后跟要使用的类型的名称来编写类型注释。
本示例为名为的变量提供类型注释welcomeMessage ,以指示该变量可以存储String 值:
- var welcomeMessage: String
声明中的冒号表示“…类型……”,因此上面的代码可以读作:
“声明一个名为welcomeMessage that的类型的变量String 。”
“类型String ”一词的意思是“可以存储任何String 值”。将其视为可以存储的“事物的类型”(或“事物的类型”)。
welcomeMessage 现在可以将变量设置为任何字符串值,而不会出现错误:
您可以在一行中定义多个相同类型的相关变量,并用逗号分隔,并在最终变量名称后添加一个类型注释,以单行表示:
- var red, green, blue: Double
笔记
在实践中很少需要编写类型注释。如果在定义的点为常量或变量提供初始值,Swift几乎总是可以推断出用于该常量或变量的类型,如Type Safety和Type Inference中所述。在welcomeMessage 上面的示例中,没有提供初始值,因此该welcomeMessage 变量的类型是通过类型注释指定的,而不是从初始值推断出来的。
命名常量和变量
常量和变量名称几乎可以包含任何字符,包括Unicode字符:
- let π = 3.14159
- let 你好 = "你好世界"
- let ???????? = "dogcow"
常量和变量名称不能包含空格字符,数学符号,箭头,专用的Unicode标量值或线条和框形图字符。它们也不能以数字开头,尽管数字可能包含在名称中的其他位置。
声明了某种类型的常量或变量后,就无法再次使用相同的名称对其进行声明,也无法将其更改为存储其他类型的值。也不能将常量更改为变量或将变量更改为常量。
笔记
如果您需要给常量或变量命名与保留的Swift关键字相同的名称,则` 在使用该关键字作为名称时,请在关键字两端加上反引号()。但是,除非绝对没有选择,否则避免将关键字用作名称。
您可以将现有变量的值更改为兼容类型的另一个值。在此示例中,的值friendlyWelcome 从更改"Hello!" 为"Bonjour!" :
- var friendlyWelcome = "Hello!"
- friendlyWelcome = "Bonjour!"
- // friendlyWelcome is now "Bonjour!"
与变量不同,常数的值在设置后不能更改。编译代码时,尝试这样做会报告为错误:
- let languageName = "Swift"
- languageName = "Swift++"
- // This is a compile-time error: languageName cannot be changed.
打印常量和变量
您可以使用以下print(_:separator:terminator:) 函数打印常量或变量的当前值:
- print(friendlyWelcome)
- // Prints "Bonjour!"
该print(_:separator:terminator:) 函数是全局函数,可将一个或多个值打印到适当的输出。例如,在Xcode中,该print(_:separator:terminator:) 函数在Xcode的“控制台”窗格中打印其输出。该separator 和terminator 参数都有默认值,这样你就可以当你调用这个函数忽略它们。默认情况下,该函数通过添加换行符来终止其打印的行。要打印后没有换行符的值,请传递一个空字符串作为终止符,例如。有关具有默认值的参数的信息,请参见“默认参数值”。print(someValue, terminator: "")
Swift使用字符串插值法将常量或变量的名称作为占位符包含在较长的字符串中,并提示Swift将其替换为该常量或变量的当前值。将名称括在括号中,并在左括号前使用反斜杠将其转义:
- print("The current value of friendlyWelcome is \(friendlyWelcome)")
- // Prints "The current value of friendlyWelcome is Bonjour!"
笔记
你可以用串插中使用的所有选项中描述字符串插值。
评论
使用注释在代码中包括不可执行的文本,作为对自己的注释或提醒。在编译代码时,Swift编译器将忽略注释。
Swift中的注释与C中的注释非常相似。单行注释以两个正斜杠(// )开头:
多行注释以正斜杠后跟星号(/* )开头,以星号后跟正斜杠(*/ )结束:
- /* 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不需要您; 在代码中的每个语句后写分号(),尽管您可以根据需要这样做。但是,如果要在一行上编写多个单独的语句,则需要使用分号:
- let cat = "????"; print(cat)
- // Prints "????"
整数
整数是没有小数部分的整数,例如42 和-23 。整数是带符号的(正,零或负)或无符号的(正或零)。
Swift提供8位,16位,32位和64位形式的有符号和无符号整数。这些整数遵循类似于C的命名约定,其中8位无符号整数的类型为UInt8 ,而32位有符号整数的类型为Int32 。像Swift中的所有类型一样,这些整数类型都有大写的名称。
整数范围
您可以使用min 和max 属性访问每个整数类型的最小值和最大值:
- let minValue = UInt8.min // minValue is equal to 0, and is of type UInt8
- let maxValue = UInt8.max // maxValue is equal to 255, and is of type UInt8
这些属性的值是适当大小的数字类型(例如,UInt8 在上面的示例中),因此可以与相同类型的其他值一起在表达式中使用。
诠释
在大多数情况下,您无需选择特定大小的整数即可在代码中使用。Swift提供了另外一个整数类型,Int 其大小与当前平台的本机字大小相同:
-
在32位平台上,
Int 与大小相同Int32 。
-
在64位平台上,
Int 与大小相同Int64 。
除非您需要使用特定大小的整数,否则请始终Int 在代码中使用整数值。这有助于代码的一致性和互操作性。即使在32位平台上,Int 也可以存储-2,147,483,648 和之间的任何值2,147,483,647 ,并且对于许多整数范围而言足够大。
UInt
Swift还提供了一个无符号整数类型,UInt 其大小与当前平台的本机字大小相同:
-
在32位平台上,
UInt 与大小相同UInt32 。
-
在64位平台上,
UInt 与大小相同UInt64 。
笔记
使用UInt 只有当你特别需要具有相同大小的平台的本地字大小的无符号整型。如果不是这种情况,那么Int 即使已知要存储的值是非负值,也还是首选。始终如一地使用Int 整数值有助于代码互操作性,避免了在不同数字类型之间进行转换的需要,并匹配了整数类型推断,如Type Safety和Type Inference中所述。
浮点数字
浮点数是具有小数部分的数字,例如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之类的语言相比,所需的类型声明要少得多。常量和变量仍然是显式输入的,但是指定它们的类型的许多工作都是为您完成的。
当您声明具有初始值的常量或变量时,类型推断特别有用。这通常是通过分配完成的文字值(或文字在你宣布它的点)的固定或可变。(A字面值是直接出现在源代码中,如一个值42 和3.14159 在下面的例子。)
例如,如果不给字面值赋42 一个新常量而没有说出它是什么类型,Swift会推断您希望该常量为Int ,因为您已经用一个看起来像整数的数字对其进行了初始化:
- let meaningOfLife = 42
- // meaningOfLife is inferred to be of type Int
同样,如果您没有为浮点文字指定类型,Swift会推断您要创建一个Double :
- let pi = 3.14159
- // pi is inferred to be of type Double
在推断浮点数的类型时,Swift总是选择Double (而不是Float )。
如果在表达式中结合使用整数和浮点文字,Double 则会从上下文中推断出的类型:
- let anotherPi = 3 + 0.14159
- // anotherPi is also inferred to be of type Double
的字面值3 本身没有显式类型,因此Double 从作为加法的一部分的浮点字面量中推断出适当的输出类型。
数字文字
整数文字可以写为:
-
一个十进制数,无前缀
-
一个二进制数,有
0b 前缀
-
一个八进制数,有
0o 前缀
-
一个十六进制数,有
0x 前缀
所有这些整数文字的十进制值为17 :
- let decimalInteger = 17
- let binaryInteger = 0b10001 // 17 in binary notation
- let octalInteger = 0o21 // 17 in octal notation
- let hexadecimalInteger = 0x11 // 17 in hexadecimal notation
浮点文字可以是十进制(无前缀)或十六进制(有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 :
- let decimalDouble = 12.1875
- let exponentDouble = 1.21875e1
- let hexadecimalDouble = 0xC.3p0
数字文字可以包含额外的格式,以使其更易于阅读。整数和浮点数都可以用额外的零填充,并且可以包含下划线以帮助提高可读性。两种格式都不会影响文字的基础值:
- let paddedDouble = 000123.456
- let oneMillion = 1_000_000
- let justOverOneMillion = 1_000_000.000_000_1
数值类型转换
将Int 类型用于代码中的所有通用整数常量和变量,即使已知它们是非负数也是如此。在日常情况下使用默认整数类型意味着整数常量和变量可立即在您的代码中互操作,并且将与推断的类型匹配整数文字值。
仅在由于即将从外部源显式调整数据大小或出于性能,内存使用或其他必要的优化而特别需要处理手头任务时,才使用其他整数类型。在这些情况下,使用显式大小的类型有助于捕获任何意外的值溢出,并隐式记录所使用数据的性质。
整数转换
对于每种数字类型,可以存储在整数常量或变量中的数字范围是不同的。一个Int8 常数或变量可以存储之间的数字-128 和127 ,而UInt8 常数或变量可以存储之间的数字0 和255 。编译代码时,将不适合整数大小或常量类型的常量的数字报告为错误:
- let cannotBeNegative: UInt8 = -1
- // UInt8 can't store negative numbers, and so this will report an error
- let tooBig: Int8 = Int8.max + 1
- // Int8 can't store a number larger than its maximum value,
- // and so this will also report an error
由于每种数字类型可以存储不同范围的值,因此您必须视情况选择加入数字类型转换。这种选择加入的方法可以防止隐藏的转换错误,并有助于在代码中明确表明类型转换的意图。
要将一种特定的数字类型转换为另一种,可以使用现有值初始化所需类型的新数字。在下面的示例中,常量twoThousand 是type UInt16 ,而常量one 是type UInt8 。不能将它们直接添加在一起,因为它们不是同一类型。相反,此示例调用UInt16(one) 创建一个新UInt16 的one ,并使用值初始化,并使用该值代替原始值:
- let twoThousand: UInt16 = 2_000
- let one: UInt8 = 1
- let twoThousandAndOne = twoThousand + UInt16(one)
因为加法的两边现在都是type UInt16 ,所以允许加法。输出常量(twoThousandAndOne )推断为type UInt16 ,因为它是两个UInt16 值的总和。
SomeType(ofInitialValue) 是调用Swift类型的初始值设定项并传递初始值的默认方式。在幕后,UInt16 有一个接受UInt8 值的初始值设定项,因此该初始值设定项用于UInt16 从现有的中创建一个新值UInt8 。但是,您不能在此处传递任何类型-它必须是为其UInt16 提供初始化程序的类型。扩展中介绍了扩展现有类型以提供接受新类型(包括您自己的类型定义)的初始化程序的功能。
整数和浮点转换
整数和浮点数字类型之间的转换必须明确:
- let three = 3
- let pointOneFourOneFiveNine = 0.14159
- let pi = Double(three) + pointOneFourOneFiveNine
- // pi equals 3.14159, and is inferred to be of type Double
在这里,常量的值three 用于创建type的新值Double ,以便加法的两面都属于同一类型。如果没有这种转换,则不允许添加。
浮点数到整数的转换也必须明确。整数类型可以使用Double 或Float 值初始化:
- let integerPi = Int(pi)
- // integerPi equals 3, and is inferred to be of type Int
以这种方式用于初始化新整数值时,浮点值始终会被截断。这意味着4.75 成为4 ,并且-3.9 成为-3 。
笔记
组合数字常量和变量的规则与数字文字的规则不同。文字值3 可以直接添加到文字值中0.14159 ,因为数字文字本身本身没有显式类型。仅在编译器对其求值时才推断出它们的类型。
类型别名
类型别名为现有类型定义备用名称。您可以使用typealias 关键字定义类型别名。
当您想通过上下文更合适的名称来引用现有类型时,例如使用外部源中特定大小的数据时,类型别名非常有用:
- typealias AudioSample = UInt16
定义类型别名后,您可以在任何可能使用原始名称的地方使用别名:
- var maxAmplitudeFound = AudioSample.min
- // maxAmplitudeFound is now 0
在此,AudioSample 被定义为的别名UInt16 。因为它是一个别名,调用AudioSample.min 实际调用UInt16.min ,它提供的初始值0 的maxAmplitudeFound 变量。
布尔值
Swift具有一个基本的布尔类型,称为Bool 。布尔值被称为逻辑值,因为它们只能是true或false。Swift提供了两个布尔常量值,true 以及false :
- let orangesAreOrange = true
- let turnipsAreDelicious = false
该类型的orangesAreOrange 和turnipsAreDelicious 被推断为Bool 一个事实,即他们与布尔文字值初始化。正如Int 和Double 上面,你并不需要声明常量或变量Bool ,如果将其设置为true 或者false 只要你创建它们。当类型推断使用其类型已知的其他值初始化常量或变量时,类型推断有助于使Swift代码更简洁易读。
当您使用条件语句(例如,if 语句)时,布尔值特别有用:
- if turnipsAreDelicious {
- print("Mmm, tasty turnips!")
- } else {
- print("Eww, turnips are horrible.")
- }
- // Prints "Eww, turnips are horrible."
诸如条件语句之类的条件语句if 在“控制流”中有更详细的介绍。
Swift的类型安全性可防止将非布尔值替换为Bool 。下面的示例报告一个编译时错误:
- let i = 1
- if i {
- // this example will not compile, and will report an error
- }
但是,下面的替代示例是有效的:
- let i = 1
- if i == 1 {
- // this example will compile successfully
- }
比较的结果是type ,因此第二个示例通过了type-check。基本运算符中讨论了类似的比较。i == 1 Bool i == 1
与Swift中的其他类型安全示例一样,此方法避免了意外错误,并确保始终清楚特定代码部分的意图。
元组
元组将多个值分组为一个复合值。元组中的值可以是任何类型,而不必彼此相同。
在此示例中,是描述HTTP状态代码的元组。HTTP状态代码是每当您请求网页时由Web服务器返回的特殊值。如果您请求一个不存在的网页,则返回状态码。(404, "Not Found") 404 Not Found
- let http404Error = (404, "Not Found")
- // http404Error is of type (Int, String), and equals (404, "Not Found")
的元组基团一起的和,得到的HTTP状态代码两个独立的值:一个数字和一个人类可读的描述。可以将其描述为“类型的元组”。(404, "Not Found") Int String (Int, String)
您可以从任何类型的排列创建元组,并且它们可以包含任意多的不同类型。没有什么阻止你有型的元组,或者,或者你确实需要的任何其他排列。(Int, Int, Int) (String, Bool)
您可以将元组的内容分解为单独的常量或变量,然后像往常一样访问它们:
- let (statusCode, statusMessage) = http404Error
- print("The status code is \(statusCode)")
- // Prints "The status code is 404"
- print("The status message is \(statusMessage)")
- // Prints "The status message is Not Found"
如果只需要一些元组的值,则_ 在分解元组时,请用下划线()忽略该元组的某些部分:
- let (justTheStatusCode, _) = http404Error
- print("The status code is \(justTheStatusCode)")
- // Prints "The status code is 404"
或者,使用从零开始的索引号访问元组中的各个元素值:
- print("The status code is \(http404Error.0)")
- // Prints "The status code is 404"
- print("The status message is \(http404Error.1)")
- // Prints "The status message is Not Found"
定义元组时,可以命名元组中的各个元素:
- let http200Status = (statusCode: 200, description: "OK")
如果在元组中命名元素,则可以使用元素名称来访问这些元素的值:
- print("The status code is \(http200Status.statusCode)")
- // Prints "The status code is 200"
- print("The status message is \(http200Status.description)")
- // Prints "The status message is OK"
元组作为函数的返回值特别有用。尝试检索网页的函数可能会返回元组类型,以描述页面检索的成功或失败。通过返回具有两个不同值(每个类型都不同)的元组,该函数提供的结果要比仅返回单个类型的单个值要有用得多。有关更多信息,请参见具有多个返回值的函数。(Int, String)
笔记
元组对于简单的一组相关值很有用。它们不适合创建复杂的数据结构。如果您的数据结构可能更复杂,则将其建模为类或结构,而不是元组。有关更多信息,请参见结构和类。
选装件
在可能不存在值的情况下,可以使用可选选项。可选的代表两种可能性:要么有是一个值,你可以解开可选访问该值,或者有没有价值可言。
笔记
可选概念在C或Objective-C中不存在。在Objective-C中,最接近的是nil 从一种方法返回的能力,该方法原本会返回一个对象,nil 意思是“缺少有效的对象”。但是,这仅适用于对象,不适用于结构,基本C类型或枚举值。对于这些类型,Objective-C方法通常返回一个特殊值(例如NSNotFound )以指示不存在值。这种方法假定方法的调用者知道要测试的特殊值,并且记住要进行检查。Swift的可选参数使您可以指示根本不需要任何类型的值,而无需特殊的常量。
这是一个示例,说明如何使用可选参数来解决缺少值的问题。Swift的Int 类型具有一个初始化程序,该初始化程序试图将一个String 值转换为一个Int 值。但是,并非每个字符串都可以转换为整数。字符串"123" 可以转换为数值123 ,但是字符串没有明显的数值可以转换为数值。"hello, world"
以下示例使用初始化程序尝试将aString 转换为Int :
- let possibleNumber = "123"
- let convertedNumber = Int(possibleNumber)
- // convertedNumber is inferred to be of type "Int?", or "optional Int"
由于初始化程序可能会失败,因此它返回一个optional Int 而不是一个Int 。可选Int 内容写为Int? 而不是Int 。问号表示它包含的值是可选的,这意味着它可能包含某个 Int 值,或者可能根本不包含任何值。(它不能包含其他任何内容,例如Bool 值或String 值。它可以是Int ,也可以完全不包含任何内容。)
零
您可以通过为可选变量分配特殊值来将其设置为无值状态nil :
- var serverResponseCode: Int? = 404
- // serverResponseCode contains an actual Int value of 404
- serverResponseCode = nil
- // serverResponseCode now contains no value
笔记
您不能使用nil 非可选的常量和变量。如果在某些情况下代码中的常量或变量需要在没有值的情况下工作,请始终将其声明为适当类型的可选值。
如果您在不提供默认值的情况下定义了一个可选变量,则该变量会自动nil 为您设置为:
|
请发表评论