Swift 可选类型

2,054 阅读4分钟

原文地址

Swift 中,使用可选类型(optionals)来表示值可能缺失的情况。可选属性存在两种可能性,一种是有值,你可以通过解包来访问这个值。另一种是根本没有值,即 nil 的情况。

Objective-C中并没有可选类型这个概念。Objective-C中一般会通过返回一个特殊值(如:NSNotFound)来暗示值的缺失。

可选类型的声明

通过在类型后面加一个问号(?)来标记这个变量的值是可选的,通过将可选变量赋值为 nil 来表示它没有值,如下:

var serverResponseCode: Int? = 404
serverResponseCode = nil

**注意:**不能将非可选类型的变量和常量赋值为nil。

如果声明一个可选类型的常量或变量,但是没有赋值,它们会被自动置为nil,如下:

var surveyAnswer: 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 = surveyAnswer else {
    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 let secondNumber = Int("42") {
        if firstNumber < secondNumber && secondNumber < 100 {
            print("\(firstNumber) < \(secondNumber) < 100")
        }
    }
}

隐式解析可选类型

我们已经知道,可选类型声明的变量或常量可能有值,也有可能没有值,我们需要通过解析来使用可选类型的值。然而,如果我们在一开始就已经确定这个可选类型一定有值,如果每次都判断和解析可选类型是非常低效的,这样,隐式解析可选类型就出现了。

隐式解析可选类型是可选类型的一种,但是可以被当做非可选类型来使用,并不需要每次都使用解析来获取可选值。它们之间唯一的区别是,隐式解析可选类型是对 Swift 编译器的一个承诺,即在运行时访问时,它的值不会为 nil

通过将可选的类型的后面的问号(String?)改成感叹号(String!)来声明一个隐式解析可选类型。

通过下面例子看一下,可选类型 String 和隐式解析可选类型 String 之间的区别:

let possibleString: String? = "An optional string."
let forcedString: String = possibleString! // 需要感叹号来获取值

let assumedString: String! = "An implicitly unwrapped optional string."
let implicitString: String = assumedString  // 不需要感叹号

**注意:**如果你在隐式解析可选类型没有值的时候尝试取值,会触发运行时错误。


扫一扫关注关注公众号,get更多技术好文