余晖落尽暮晚霞,黄昏迟暮远山寻
本站
当前位置:网站首页 > 编程知识 > 正文

Swift 4.1 官方文档大全(第二章)基本语法(swift用法)

xiyangw 2022-12-03 12:04 23 浏览 0 评论

基础

Swift是iOS,macOS,watchOS和tvOS应用程序开发的新编程语言。尽管如此,Swift的很多部分都将从您在C和Objective-C中开发的经验中熟悉起来。

Swift 4.1 官方文档大全(第二章)基本语法(swift用法)

Swift提供了它自己的所有基本C和Objective-C类型的版本,包括用于整数的Int,用于浮点值的Double和Float,用于布尔值的Bool和用于文本数据的String。 Swift还提供了三种主要集合类型的强大版本,如集合类型中所述的Array,Set和Dictionary。

像C一样,Swift使用变量来存储和引用一个识别名称的值。 Swift也广泛使用其值不能改变的变量。这些被称为常量,并且比C中的常量强大得多。当您使用不需要更改的值时,常量在Swift中用于使代码更安全和更清晰。

除了熟悉的类型之外,Swift还引入了在Objective-C中找不到的高级类型,例如元组。元组使您能够创建和传递值组。您可以使用元组作为单个复合值从函数中返回多个值。

Swift还引入了可选类型,它处理缺少值的情况。可选项:“有价值,它等于x”或“根本没有价值”。使用optionals类似于在Objective-C中使用零指针,但它们适用于任何类型,而不仅仅是类。 Objective-C中的option指针不仅比零指针更安全,更具表现力,它们是Swift最强大功能中的核心。

Swift是一种类型安全的语言,这意味着该语言可以帮助您清楚您的代码可以使用的值的类型。如果部分代码需要一个字符串,则类型安全性会阻止您错误地向它传递一个Int。同样,类型安全性可防止您意外地将可选字符串传递给需要非可选字符串的代码片段。类型安全可以帮助您在开发过程中尽早捕获并修复错误。

常量和变量

常量和变量将名称(例如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的类型为String的变量。”

“字符串类型”这个短语的意思是“可以存储任何字符串值”。可以把它看作是可以存储的“事物类型”(或“事物类型”)的含义。

welcomeMessage变量现在可以设置为任何字符串值而不会出错:

welcomeMessage = "Hello"

您可以在一行中定义多个相同类型的相关变量,用逗号分隔,最后一个变量名称后面带有单个类型注释:

var red, green, blue: Double

注意

在实践中你很少需要编写类型注释。 如果您在定义点处为常量或变量提供初始值,则Swift几乎总是可以推断出该常量或变量所用的类型,如类型安全和类型推断中所述。 在上面的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的“控制台”窗格中。 分隔符和终止符参数具有默认值,因此您可以在调用此函数时省略它们。 默认情况下,该函数通过添加换行符终止它打印的行。 要在后面打印没有换行符的值,请传递一个空字符串作为终止符 - 例如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 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不要求您在代码中的每个语句后都写一个分号(;),尽管如果您愿意的话可以这样做。 但是,如果要在单行中编写多个单独的语句,则需要分号:

let cat = ""; print(cat)

// Prints ""

整型

整数是没有小数分量的整数,例如42和-23。 整数是有符号的(正数,零或负数)或无符号数(正数或零)。

Swift以8,16,32和64位格式提供有符号和无符号整数。 这些整数遵循类似于C的命名约定,即一个8位无符号整数是UInt8类型,而一个32位有符号整数是Int32类型。 像Swift中的所有类型一样,这些整数类型都有大写的名字。

整数界限

您可以使用其最小和最大属性访问每个整数类型的最小值和最大值:

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一致地使用整数值有助于代码互操作性,避免了在不同数字类型之间进行转换的需要,并匹配整数类型推断,如类型安全和类型推断中所述。

浮点数字

浮点数是具有小数分量的数字,例如3.14159,0.1和-273.15。

浮点类型可以表示比整数类型更宽的值范围,并且可以存储比可以存储在Int中的数字更大或更小的数字。 Swift提供了两个有符号的浮点数类型:

Double表示一个64位浮点数。

Float表示一个32位浮点数。

注意

Double的精度至少为15个十进制数字,而Float的精度可以小至6个十进制数字。 要使用的适当的浮点类型取决于代码中需要使用的值的性质和范围。 在任何一种类型都适合的情况下,Double是首选。

类型安全和类型推断

Swift是一种类型安全的语言。类型安全的语言鼓励您清楚您的代码可以使用的值的类型。如果你的部分代码需要一个字符串,你不能错误地将它传递给一个Int。

因为Swift是类型安全的,所以它在编译代码时执行类型检查并将任何不匹配的类型标记为错误。这使您能够在开发过程中尽早捕获并修复错误。

类型检查有助于避免在使用不同类型的值时发生错误。但是,这并不意味着您必须指定您声明的每个常量和变量的类型。如果你没有指定你需要的值的类型,Swift使用类型推断来计算出合适的类型。类型推断使编译器能够在编译代码时自动推断特定表达式的类型,只需检查您提供的值即可。

由于类型推理,Swift比C或Objective-C等语言所需的类型声明要少得多。常量和变量仍然是明确的类型,但是很多指定类型的工作都是为你完成的。

当您使用初始值声明常量或变量时,类型推断特别有用。这通常是通过在声明它的点处为常量或变量赋予一个文字值(或文字)来完成的。 (文字值是直接出现在您的源代码中的值,例如下面的示例中的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前缀

一个八进制数,前缀为0

一个十六进制数字,带有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的十进制数,基数乘以10exp:

1.25e2 means 1.25 x 102, or 125.0.

1.25e-2 means 1.25 x 10-2, or 0.0125.

对于指数为exp的十六进制数,基数乘以2exp:

0xFp2 means 15 x 22, or 60.0.

0xFp-2 means 15 x 2-2, or 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 cannot store negative numbers, and so this will report an error

let tooBig: Int8 = Int8.max + 1

// Int8 cannot store a number larger than its maximum value,

// and so this will also report an error

由于每种数字类型都可以存储不同范围的值,因此您必须逐个选择数字类型转换。 这种选择加入方法可以防止隐藏的转换错误,并有助于在代码中明确类型转换意图。

要将一个特定的号码类型转换为另一个号码类型,您需要使用现有的值初始化一个所需类型的新号码。 在下面的例子中,常量twoThousand的类型是UInt16,而常量的是UInt8的类型。 它们不能直接加在一起,因为它们不是同一类型。 相反,这个例子调用UInt16(一)来创建一个新值为1的新UInt16,并使用该值代替原始值:

let twoThousand: UInt16 = 2_000

let one: UInt8 = 1

let twoThousandAndOne = twoThousand + UInt16(one)

因为添加的两侧现在都是UInt16类型,所以允许添加。 输出常量(twoThousandAndOne)被推断为UInt16类型,因为它是两个UInt16值的总和。

SomeType(ofInitialValue)是调用Swift类型的初始值设定项并传入初始值的默认方式。 在幕后,UInt16有一个接受UInt8值的初始化程序,所以这个初始化程序用于从现有的UInt8创建一个新的UInt16。 但是,这里不能传入任何类型,它必须是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

这里,常量三的值用于创建一个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关键字定义类型别名。

如果要通过上下文更合适的名称引用现有类型,例如在从外部源处理特定大小的数据时,类型别名很有用:

typealiasAudioSample = UInt16

一旦你定义了一个类型别名,你可以在任何你可能使用原始名称的地方使用别名:

var maxAmplitudeFound = AudioSample.min

// maxAmplitudeFound is now 0

这里,AudioSample被定义为UInt16的别名。 因为它是一个别名,所以对AudioSample.min的调用实际上调用了UInt16.min,它为maxAmplitudeFound变量提供了初始值0。


布尔

Swift有一个基本的布尔类型,称为Bool。 布尔值被称为逻辑,因为它们只能是真或假。 Swift提供了两个布尔常量值,true和false:

let orangesAreOrange = true

let turnipsAreDelicious = false

OrangesAreOrange和turnipsAreDelicious的类型已经被推断为Bool,因为它们是用布尔文字值初始化的。 与上面的Int和Double一样,如果您创建它们时将它们设置为true或false,则不需要将常量或变量声明为Bool。 当使用类型已知的其他值初始化常量或变量时,类型推断有助于使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

}

i == 1比较的结果是Bool类型,因此第二个示例通过类型检查。 比如i == 1在Basic Operators中讨论。

与Swift中的其他类型安全示例一样,这种方法避免了意外错误,并确保特定代码段的意图始终清晰。


元组

元组将多个值组合为一个复合值。 元组中的值可以是任何类型,不必是彼此相同的类型。

在这个例子中,(404,“Not Found”)是一个描述HTTP状态码的元组。 每当您请求网页时,HTTP状态码都是Web服务器返回的特殊值。 如果您请求不存在的网页,则会返回404 Not Found的状态代码。

let http404Error = (404, "Not Found")

// http404Error is of type (Int, String), and equals (404, "Not Found")

404,“Not Found”)元组将Int和String组合在一起以给HTTP状态码两个单独的值:一个数字和一个可读的描述。 它可以被描述为“一个类型的元组(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”没有明显的数字值转换。

下面的例子使用初始化器尝试将String转换为Int:

let possibleNumber = "123"

let convertedNumber = Int(possibleNumber)

// convertedNumber is inferred to be of type "Int?", or "optional Int"

由于初始化程序可能会失败,它会返回一个可选的Int,而不是Int。 可选的Int被写为Int ?,而不是Int。 问号表示它包含的值是可选的,这意味着它可能包含一些Int值,或者它可能根本不包含任何值。 (它不能包含任何其他内容,例如Bool值或String值,它可以是Int,也可以不包含任何内容。)

Nil

通过给可选变量赋予特殊值nil来将可选变量设置为无值状态:

var serverResponseCode: Int? = 404

// serverResponseCode contains an actual Int value of 404

serverResponseCode = nil

// serverResponseCode now contains no value

注意

你不能在非任意常量和变量中使用nil。 如果代码中的常量或变量需要在某些条件下没有值时使用,则始终将其声明为适当类型的可选值。

如果您定义了一个可选变量而不提供默认值,则该变量会自动设置为零:

var surveyAnswer: String?

// surveyAnswer is automatically set to nil

注意

Swift的零与Objective-C中的零不相同。 在Objective-C中,nil是一个指向不存在对象的指针。 在Swift中,nil不是一个指针 - 它是缺少某种类型的值。 任何类型的选项可以设置为零,而不仅仅是对象类型。

if陈述和强制解包

您可以使用if语句通过将可选项与nil进行比较来确定可选项是否包含值。 用“等于”运算符(==)或“不等于”运算符(!=)执行此比较。

如果可选值有一个值,则认为它“不等于”零:

if convertedNumber != nil {

print("convertedNumber contains some integer value.")

}

// Prints "convertedNumber contains some integer value."

一旦确定可选项包含值,您可以通过在可选名称的末尾添加感叹号(!)来访问其基础值。 感叹号有效地说:“我知道这个可选项肯定有价值; 请使用它“。这称为强制展开可选值:

if convertedNumber != nil {

print("convertedNumber has an integer value of \(convertedNumber!).")

}

// Prints "convertedNumber has an integer value of 123."

有关if语句的更多信息,请参见控制流。

注意

试图使用! 访问不存在的可选值会触发运行时错误。 在使用之前,务必确保可选项包含非零值! 强制 - 解开其价值。

可选绑定

您使用可选绑定来确定可选是否包含值,如果是,则将该值作为临时常量或变量提供。 可选绑定可以与if和while语句一起使用,以检查可选内部的值,并将该值提取为常量或变量,作为单个操作的一部分。 if和while语句在控制流程中有更详细的描述。

为if语句编写可选绑定,如下所示:

  • if let constantName = someOptional {

  • statements

  • }

您可以重写Optionalals部分中的possibleNumber示例以使用可选绑定而不是强制展开:

if let actualNumber = Int(possibleNumber) {

print("\"\(possibleNumber)\" has an integer value of \(actualNumber)")

} else {

print("\"\(possibleNumber)\" could not be converted to an integer")

}

// Prints ""123" has an integer value of 123"

他的代码可以被理解为:

“如果由Int(possibleNumber)返回的可选Int包含一个值,则将一个名为actualNumber的新常量设置为包含在可选项中的值。”

如果转换成功,那么actualNumber常量可用于if语句的第一个分支内。它已经被初始化为包含在可选项中的值,所以不需要使用!后缀以访问其值。在本例中,actualNumber仅用于打印转换结果。

您可以使用可选绑定的常量和变量。如果要在if语句的第一个分支内操作actualNumber的值,则可以编写if var actualNumber,而将可选内容包含在变量中而不是常量中。

您可以根据需要在单个if语句中包含尽可能多的可选绑定和布尔条件,并用逗号分隔。如果可选绑定中的任何值为零,或者任何布尔条件的计算结果为false,则整个if语句的条件被认为是错误的。以下if语句是等价的:

if let firstNumber = Int("4"), let secondNumber = Int("42"), firstNumber < secondNumber && secondNumber < 100 {

print("\(firstNumber) < \(secondNumber) < 100")

}

// Prints "4 < 42 < 100"

if let firstNumber = Int("4") {

if let secondNumber = Int("42") {

if firstNumber < secondNumber && secondNumber < 100 {

print("\(firstNumber) < \(secondNumber) < 100")

}

}

}

// Prints "4 < 42 < 100"

注意

在if语句中使用可选绑定创建的常量和变量仅在if语句的主体中可用。相反,使用guard语句创建的常量和变量在Guard语句后面的代码行中可用,如Early Exit中所述。

隐式解包选项

如上所述,可选项表示允许常量或变量具有“无值”。可以使用if语句检查选项,以查看是否存在值,并且可以使用可选绑定有条件地解包,以访问可选值(如果存在)。

有时候从程序的结构中可以清楚地看到,在第一次设置值之后,可选项将始终有一个值。在这些情况下,每次访问时都不必检查和打开可选的值,因为可以安全地假定所有时间都有值。

这些选项被定义为隐式解包选项。通过在想要进行选择的类型后放置感叹号(String!)而不是问号(String?),可以编写一个隐式解包的可选项。

当可选值被确定为在第一次定义可选值后立即存在,并且肯定可以假设其后每一点都存在时,隐式解包的可选值就很有用。 Swift中隐式展开选项的主要用途是在类初始化期间,如Unowned References和Unviousned Unwrapped Optional Properties中所述。

隐式解包可选是幕后的普通可选,但也可以像非可选值一样使用,而不必在每次访问时解开可选值。以下示例显示了在以可显示的字符串形式访问其包装值时,可选字符串与隐式解包的可选字符串之间的行为差异:

let possibleString: String? = "An optional string."

let forcedString: String = possibleString! // requires an exclamation mark

let assumedString: String! = "An implicitly unwrapped optional string."

let implicitString: String = assumedString// no need for an exclamation mark

你可以想象一个隐式解包的可选方案,因为只要使用它就可以自动解包可选的权限。 每次使用该名称时,不要在可选名称后面放置感叹号,而要在声明它时在可选类型后面放置感叹号。

注意

如果隐式解包的可选项为零,并且您尝试访问其包装的值,则会触发运行时错误。 结果与在不包含值的普通可选项后放置感叹号完全相同。

你仍然可以像一个普通的可选项那样处理隐式解包的可选项,以检查它是否包含值:

if assumedString != nil {

print(assumedString!)

}

// Prints "An implicitly unwrapped optional string."

你也可以使用一个带有可选绑定的隐式解包的可选方法,在一个语句中检查和打开它的值:

if let definiteString = assumedString {

print(definiteString)

}

// Prints "An implicitly unwrapped optional string."

注意

当稍后有可能变量为零时,不要使用隐式解包的可选项。 如果您需要在变量的生命周期中检查零值,则始终使用正常的可选类型。


错误处理

您可以使用错误处理来响应程序在执行过程中可能遇到的错误情况。

与可以使用值的存在或不存在来传递函数的成功或失败的可选项相比,错误处理允许您确定失败的根本原因,并在必要时将错误传播到程序的另一部分。

当函数遇到错误情况时,它会引发错误。 然后该函数的调用者可以捕获错误并做出适当的响应。

func canThrowAnError() throws {

// this function may or may not throw an error

}

函数指示它可以通过在其声明中包含throws关键字来引发错误。 当你调用一个可能引发错误的函数时,你需要在表达式中加上try关键字。

Swift会自动将错误传播出当前范围,直到它们被catch子句处理。

do {

try canThrowAnError()

// no error was thrown

} catch {

// an error was thrown

}

do语句创建一个新的包含范围,它允许将错误传播到一个或多个catch子句。

以下是错误处理如何用于响应不同错误情况的示例:

func makeASandwich() throws {

// ...

}

do {

try makeASandwich()

eatASandwich()

} catch SandwichError.outOfCleanDishes {

washDishes()

} catch SandwichError.missingIngredients(letingredients) {

buyGroceries(ingredients)

}

在这个例子中,如果没有干净的盘子或缺少任何配料,makeASandwich()函数将会报错。因为makeASandwich()可能会引发错误,所以函数调用被包装在try表达式中。通过将函数调用包装在do语句中,抛出的任何错误都会传播到提供的catch子句。

如果没有错误发生,则调用eatASandwich()函数。如果抛出一个错误并且它与SandwichError.outOfCleanDishes大小写匹配,那么将调用washDishes()函数。如果抛出一个错误,并且它与SandwichError.missingIngredients案件相匹配,则使用catch模式捕获的关联[String]值调用buyGroceries(_ :)函数。

错误处理中详细介绍了投掷,捕捉和传播错误。

断言和先决条件

断言和先决条件是在运行时发生的检查。在执行任何进一步的代码之前,您可以使用它们来确保满足基本条件。如果断言或前提条件中的布尔条件评估为true,则代码继续照常执行。如果条件评估为false,则该程序的当前状态无效;代码执行结束,并且您的应用程序被终止。

您使用断言和先决条件来表达您所做的假设和编码时的期望,以便您可以将它们包含在代码中。断言有助于您在开发过程中发现错误和不正确的假设,并且先决条件可帮助您检测生产中的问题。

除了在运行时验证您的期望之外,断言和先决条件也成为代码中有用的文档形式。与上述错误处理中讨论的错误条件不同,断言和先决条件不用于可恢复或预期的错误。由于失败的断言或先决条件表示无效的程序状态,因此无法捕获失败的断言。

使用断言和先决条件不能取代设计代码的方式,使得不可能出现无效条件。但是,使用它们来强制执行有效的数据和状态会导致应用程序在发生无效状态时更可预测地终止,并且有助于使问题更易于调试。一旦检测到无效状态,立即停止执行也有助于限制由该无效状态引起的损害。

断言和先决条件之间的区别在于它们被检查时:断言仅在调试版本中检查,但在调试版本和生产版本中都检查了先决条件。在生产构建中,断言内的条件不被评估。这意味着您可以在开发过程中使用尽可能多的断言,而不会影响生产性能。

使用断言进行调试

你可以通过调用Swift标准库中的assert(_:_:file:line :)函数来编写断言。如果条件的结果为假,则将此函数传递给一个表达式,该表达式的值为true或false,并显示一条消息。例如:

let age = -3

assert(age >= 0, "A person's age can't be less than zero.")

// This assertion fails because -3 is not >= 0.

在这个例子中,如果age> = 0的计算结果为true,那么代码将继续执行,即如果age的值非负。 如果age的值是负数,如上面的代码所示,那么age> = 0的计算结果为false,并且断言失败,终止应用程序。

你可以省略断言信息 - 例如,当它只是重复作为散文的条件。

assert(age >= 0)

如果代码已经检查了条件,则使用assertionFailure(_:file:line :)函数来指示断言失败。 例如:

if age > 10 {

print("You can ride the roller-coaster or the ferris wheel.")

} else if age > 0 {

print("You can ride the ferris wheel.")

} else {

assertionFailure("A person's age can't be less than zero.")

}

执行先决条件

只要条件有可能为假,就要使用前提条件,但必须对代码继续执行而言必须如此。 例如,使用前提条件检查下标是否超出界限,或者检查函数是否已传递有效值。

您通过调用前提条件precondition(_:_:file:line:)函数来编写前提条件。 如果条件的结果为假,则将此函数传递给一个表达式,该表达式的值为true或false,并显示一条消息。 例如:

// In the implementation of a subscript...

precondition(index > 0, "Index must be greater than zero.")

您也可以调用preconditionFailure(_:file:line :)函数来指示发生了故障 - 例如,如果采取了开关的默认情况,但所有有效的输入数据都应由交换机的其中一个处理 其他情况。

注意

如果以非检查模式编译(-Ounchecked),则不会检查前提条件。 编译器假定前提条件始终为真,并相应地优化您的代码。 但是,无论优化设置如何,fatalError(_:file:line :)函数总是会暂停执行。

通过将fatalError(“Unimplemented”)作为存根实现,您可以在原型设计和早期开发中使用fatalError(_:file:line :)函数为尚未实现的功能创建存根。 由于致命错误永远不会被优化,与断言或前提条件不同,您可以确保执行始终在遇到存根实现时暂停。

相关推荐

实训写的html电商网页代码(个人简历html网页代码)
实训写的html电商网页代码(个人简历html网页代码)

<!DOCTYPEhtml><html><head><metacharset="UTF-8"><tit...

2023-03-21 20:07 xiyangw

html常用代码大全(html全部代码表)

1.结构性定义文件类型<HTML></HTML>(放在档案的开头与结尾)文件主题<TITLE></TITLE>(必须放在「文头」区块内)文头&...

让人“头痛欲裂”的JavaScript的小代码(javascript代码大全)

前言不知道各位Web前端坑中的朋友们有没有遇到过一些让自己“头痛欲裂”的代码?我就遇到过很多,不是说人家写的不好,还是写的太“好”了。这个加引号的意思是:这些代码写很简洁,不过个人感觉有些“偏门”,导...

500行JS代码打造你的专属GIT(实用js代码)

这篇短文将介绍如何用500行的Javascript代码,写一个你自己专属的GIT。这不是一个如何使用GIT的工具,而是GIT的底层实现。目的是希望能加深对GIT的底层实现原理,而不是想换掉GIT,这...

用JS解密工具轻松解密JS代码(js密码加密解密)

当今的网络世界,JavaScript(JS)被广泛应用于网页开发和应用程序设计。然而,由于JavaScript代码的易读性,许多人担心这种脚本语言的安全性,它容易受到黑客攻击和信息窃取。因此,JS加密...

常用的JS代码片段-业务功能(js经典代码)

判断所有数据类型@paramobj要判断类型的数据@return{string}数据类型(小写)consttype=(function(){//映射类型constcl...

项目中用到的部分js代码(项目代码怎么获取)

项目中用到的通用代码,exportdefault{getCommonImgCode:function(vueObj){vueObj.$http({method:'get',ur...

13 行 JavaScript 代码让你看起来像是高手(javascript小游戏代码)

Javascript可以做许多神奇的事情,也有很多东西需要学习,今天我们介绍几个短小精悍的代码段。获取随机布尔值(True/False)使用Math.random()会返回0到1的随机数...

一个简单的 HTML 网页设计代码(简单html网页范例)

<!DOCTYPEhtml><html><head><title>我的网页</title></head><body>...

一句代码判断javascript中所有数据类型(javascript判断数据类型的方法有)
一句代码判断javascript中所有数据类型(javascript判断数据类型的方法有)

javascript中有6种基本数据类型:字符串(String)、数字(Number)、布尔(Boolean)、空(Null)、未定义(Undefined)、S...

2023-03-21 20:05 xiyangw

你是否了解的几种JavaScript 代码技巧(你是否了解内控及合规的含义)

1.多表达式多if判断我们可以在数组中存储多个值,并且可以使用数组include方法。`//长``if(x==='abc'||x==='def'...

js优化代码分支(代码优化分为)

//优化前functionspeak(name){if(name==='老牛'){console.log('老牛咩咩叫');}elseif(...

亚马逊描述中支持的常用HTML代码(亚马逊产品描述html代码)

亚马逊描述中支持的常用HTML代码:1.换行符号<br>第一行内容<br>第二行内容<br>第三行内容2.加粗符号<b></b>&...

14个 JavaScript 代码优化技巧(javascript九九乘法表代码)
14个 JavaScript 代码优化技巧(javascript九九乘法表代码)

作者|MahdhiRezvi译者|王强策划|李俊辰转发链接:https://mp.weixin.qq.com/s/veJ6mhxd5XwVG4OF...

2023-03-21 20:04 xiyangw

给你看一段javascript代码(模拟类)(javascript模拟器)
给你看一段javascript代码(模拟类)(javascript模拟器)

懂得可以欢迎提补充,不懂得欢迎学习一起进步!varClass=function(){varklass=function(){this.init.appl...

2023-03-21 20:04 xiyangw

取消回复欢迎 发表评论: