可选类型
使用可选类型来处理值可能缺失的情况。可选类型表示:
有值,等于x
或者
没有值
来看一个例子,swift的int类型有一种构造器,作用是将一个string值转换成int值。然而,并不知所有的字符串都可以转换成一个整数。字符串“123”可以转换成数字123,但是字符串“hello,world”不行。
下面的例子使用这种构造器来尝试将一个string转换成int:
let possibleNumber = "123"
let convertedNumber = Int(possibleNumber)
因为该构造器可能会失败,所以它返回一个可选类型int,而不是一个int。一个可选的int被写作int?而不是int。问号暗示包含的值是可选类型,也就是说可能包含int值也可能不包含值。
nil
你可以给可选变量赋值为nil来表示它没有值:
var serverResponseCode:Int? = 404
serverResponseCode = nil
如果声明了一个可选常量或者变量但是没有赋值,他们会自动被设置为nil:
var surveyAnswer: String?
注意:
swift的nil和oc中的nil并不一样。在oc中,nil是一个指向不存在对象的指针。在swift中,nil不是指针——他是一个确定的值,用来表示值的缺失。任何类型的可选状态都可以被设置为nil,不只是对象类型。
if语句以及强制解析
你可以使用if语句和nil比较来判断一个可选值是否包含值。你可以使用“相等”(==)或者“不等”(!=)来执行比较。
如果可选类型有值,它将不等于nil:
if surveyAnswer != nil{
print("123")
}
当你确定可选类型确实包含值之后,你可以在可选的名字后面加一个感叹号来获取值。这个表示“我知道这个可选有值,请使用它。”这被称为可选值的强制解析:
if surveyAnswer != nil{
print("surveyAnswer has an integer value of \(surveyAnswer!)")
}
使用!来获取一个不存在的可选值可能会导致运行时错误。使用!来强制解析值之前,一定要确定可选包含一个非nil的值。
可选绑定
使用可选绑定来判断可选类型是否包含值,如果包含就把值赋给一个临时常量或者变量。可选绑定可以用在if和while语句中,这条语句不仅可以用来判断可选类型中是否有值,同时可以将可选类型中的值赋给一个常量或者变量。
if let constantName = someOptional {
statements
}
这段代码可以被理解为:
如果someOptional返回的可选包含一个值,创建一个叫做constantName的新常量并将可选包含的值赋给它。
如果转换成功,constantName就能在if分支里使用。它已经被可选类型包含的值初始化过,所以不需要再使用!后缀来获取它的值。这个例子中,constantName只被用来输出转换结果。
可以包含多个可选绑定或多个布尔条件在一个if语句中,只要使用逗号分开就行。只要有任意一个可选绑定的值为nil,或者任意个亿布尔条件为false,则整个if条件判断为false,这时你就需要使用嵌套if条件语句来处理。
if let firstNumber = Int("4"), let secondNumber = Int("42") {
print("\(firstNumber) \(secondNumber)")
}
隐式解析可选类型
可选类型暗示了常量或者变量可以“没有值”。可选可以通过if语句来判断是否有值,如果有值的话可以通过可选绑定来解析值。
有时候在程序架构中,第一次被赋值之后,可以确定一个可选类型总会有值。在这种情况下,每次都要判断和解析可选值是非常低效的,因为可以确定它总会有值。
这种类型的可选状态被定义为隐式解析可选类型。把想要用作可选的类型的后面的问号改成感叹号来声明一个隐式解析可选类型。
当可选类型被一次赋值之后就可以确定之后一直有值的时候,隐式解析可选类型非常有用。隐式解析可选类型主要被用在swift中类的构造过程中。
一个隐式解析可选类型其实就是一个普通的可选类型,但是可以被当做非可选类型来使用,并不需要每次都使用解析来获取可选值。下面的例子展示了可选类型string和隐式解析可选类型string之间的区别:
let possibleString:String? = "An optional string"
let forceString:String = possibleString!
let assumedString:String! = "An implicitly unwrapped optional string"
let implicitString:String = assumedString
你可以把隐式解析可选类型当做一个可以自动解析的可选类型。要做的只是声明的时候把感叹号放到类型的结尾,而不是每次取值的可选名字的结尾。
仍然可以把隐式解析可选类型当做普通可选类型来判断它是否包含值:
if assumedString != nil{
print(assumedString)
}
可以在可选绑定中使用隐式解析可选类型来检查并解析它的值:
if let definiteString = assumedString{
print(definiteString)
}
错误处理
当一个函数遇到错误条件,他能报错。调用函数的地方能抛出错误消息并合理处理。
func canThrowAnError() throws{
}
一个函数可以通过在声明中添加throws关键词来抛出错误消息。当你的函数能够抛出错误消息时,你应该在表达式中前置try关键词。
do {
try canThrowAnError()
} catch {
}
断言
可选类型可以让你判断值是否存在,可以在代码中优雅的处理值缺失的情况。然而,在某些情况下,如果值缺失或者值并不满足特定的条件,你的带啊可能没有办法继续执行。这时,你可以在你的代码中触发一个断言来结束代码运行并通过调试来找到值缺失的原因。
使用断言进行调试
断言会在运行时判断一个逻辑条件是否为true。从字面意思来说,断言“断言”一个条件是否为真。你可以使用断言来保证在运行其他代码之前,某些重要的条件已经被满足。如果条件判断为true,代码运行会继续进行;如果条件判断为false,代码执行结束,你的应用被终止。
如果你的代码在调试环境下触发了一个断言,比如你在Xcode中构建并运行了一个应用,你可以清楚看到不合法的状态发生在哪里并检查断言被触发时你的应用的状态。此外,断言允许你附加一条调试信息。
可以使用全局assert(_:_:file:line:)函数来写一个断言。向这个函数出入一个结果为true或者false的表达式以及一条信息,当表达式的结果Wiefalse的时候这条信息会被显示:
let age = -3
assert(age >= 0 ,"can not be less than zero")
这个例子中,只有age >= 0为true的时候,既age的值非负的时候,代码才会继续执行。如果age的值是负数,就会触发断言,终止应用。
何时使用断言
当条件可能为假时使用断言,但是最终一定要保证条件为真,这样你的代码才能继续运行。断言的使用情景:
1、整数类型的下标索引被传入一个自定义下标实现,但是下标索引值可能太小或者太大。
2、需要给函数出入一个值,但是非法的值可能导致函数不能正常执行。
3、一个可选值现在是nil,但是后面的代码运行需要一个非nil值。
取自《the swift programming language》中文版