原文地址
在 Swift 中,使用可选类型(optionals)来表示值可能缺失的情况。可选属性存在两种可能性,一种是有值,你可以通过解包来访问这个值。另一种是根本没有值,即 nil 的情况。
Objective-C中并没有可选类型这个概念。Objective-C中一般会通过返回一个特殊值(如:NSNotFound)来暗示值的缺失。
可选类型的声明
通过在类型后面加一个问号(?)来标记这个变量的值是可选的,通过将可选变量赋值为 nil 来表示它没有值,如下:
varserverResponseCode:Int? =404
serverResponseCode = nil
注意:不能将非可选类型的变量和常量赋值为nil。
如果声明一个可选类型的常量或变量,但是没有赋值,它们会被自动置为nil,如下:
varsurveyAnswer:String?// surveyAnswer 被自动设置为 nil
注意:Swift 中的nil和 Objective-C 中的nil并不一样。Objective-C 中的nil是一个指向不存在对象的指针。Swift中的nil不是指针--它是一个确定的值,用来表示值缺失。任何类型的可选状态都可以被设置为nil,不只是对象类型。
可选类型解析
强制解析
使用 if 语句来判断可选类型的值是否为空,即通过是否和 nil 相等来判断可选类型是否有值,如下:
if surveyAnswer != nil {
print("surveyAnswer has a value.")
}
当确定可选类型一定有值时,可以在可选类型的名字后面加一个感叹号(!)来获取值,这个感叹号表示“我知道这个可选有值,请使用它。如下:
surveyAnswer ="一定有值"
if surveyAnswer != nil {
print(surveyAnswer!)//使用 !进行强制解析
} else{
print("值为nil")
}
注意:强制解包是一种危险的行为,一旦解包失败,就有可能崩溃。
可选绑定(optional binding)
使用可选绑定来判断可选类型是否有值,如果包含就把值赋给一个临时的变量或常量。可选绑定可以用在 if 和 while 语句中,这条语句不仅可以用来判断可选类型是否有值,同时可以将可选类型的值赋给一个常量或者变量。
下面看下如何在 if 语句中使用可选绑定:
if actualAnswer = surveyAnswer {
print(surveyAnswer)//不需要使用 !进行强制解析
} else {
print("值为nil")
}
类似的,我们还可以使用 guard let 的方式来进行解包,如下:
guard let actualAnswer = surveyAnswerelse {
print("值为nil")
}
print(surveyAnswer) //不需要使用 !进行强制解析
在 guard let 中,else 中的大括号是异常情况。而外部主体是正常的情况。
还可以在一个 if 语句中包含多个可选绑定或布尔条件,中间用逗号分割。只要任意一个可选绑定的值为 nil ,或者任意布尔条件为 false,则整个 if 条件为 false,下面两个语句是等价的:
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 letsecondNumber = Int("42") {
if firstNumber < secondNumber && secondNumber <100 {
print("\(firstNumber)<\(secondNumber)< 100")
}
}
}
隐式解析可选类型
我们已经知道,可选类型声明的变量或常量可能有值,也有可能没有值,我们需要通过解析来使用可选类型的值。然而,如果我们在一开始就已经确定这个可选类型一定有值,如果每次都判断和解析可选类型是非常低效的,这样,隐式解析可选类型就出现了。
隐式解析可选类型是可选类型的一种,但是可以被当做非可选类型来使用,并不需要每次都使用解析来获取可选值。它们之间唯一的区别是,隐式解析可选类型是对 Swift 编译器的一个承诺,即在运行时访问时,它的值不会为 nil。
通过将可选的类型的后面的问号(String?)改成感叹号(String!)来声明一个隐式解析可选类型。
通过下面例子看一下,可选类型 String 和隐式解析可选类型 String 之间的区别:
let possibleString:String? = "An optional string."
letforcedString:String= possibleString!// 需要感叹号来获取值
letassumedString:String! ="An implicitly unwrapped optional string."
letimplicitString:String= assumedString // 不需要感叹号
注意:如果你在隐式解析可选类型没有值的时候尝试取值,会触发运行时错误。