首页 Swift中的可选链
文章
取消

Swift中的可选链

Swift 是一门类型安全的语言,这意味着所有的类型必须在编译时就已经确定。然而,在真实的情况下,我们通常会遇到需要使用变量、属性或方法的场景,但是这些对象并不总是有效存在的,例如一个可能为空的变量。针对这种情况,Swift 提供了可选类型。可选类型允许我们表示一个值不存在的情况。

当我们尝试访问一个空的可选类型变量的成员时,程序就会崩溃,并抛出一个运行时错误。为了避免这种情况,Swift 引入了可选链。

可选链提供了一种安全地调用方法、属性、下标等成员的方式,即使这个成员可能为空,也能够避免程序崩溃。

可选链的语法

通过在调用成员之前加上问号(?),我们可以创建一个可选链。如果该成员存在,则返回它的值;否则,整个可选链表达式返回 nil。

以下是可选链的基本语法:

1
2
3
optionalValue?.method()
optionalValue?.property
optionalValue?[index]

其中 optionalValue 是一个可能为空的值。如果 optionalValue 为空,那么整个表达式将直接返回 nil,而不是引发运行时错误。

注意,可选链只是一种安全调用成员的方法,它并不修改被调用的成员,因此即使整个可选链表达式返回 nil,被调用的成员仍然保持不变。

调用方法

假设我们有一个 Person 类型的实例,它包含一个名为 fullName() 的方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Person {
    var firstName: String
    var lastName: String
    
    init(firstName: String, lastName: String) {
        self.firstName = firstName
        self.lastName = lastName
    }
    
    func fullName() -> String {
        return "\(self.firstName) \(self.lastName)"
    }
}

let person: Person? = Person(firstName: "John", lastName: "Doe")

现在,我们可以通过可选链来调用 person 实例的 fullName() 方法:

1
let fullName = person?.fullName()

如果 person 实例为空,那么 fullName 的值将是 nil。否则,它将包含 fullName() 方法的返回值。

访问属性

除了调用方法外,我们还可以使用可选链来访问属性。假设我们有一个类似于下面的 Car 类型:

1
2
3
4
5
6
7
8
class Car {
    var model: String
    var price: Int?
    
    init(model: String) {
        self.model = model
    }
}

现在,我们创建了一个 Car 实例,并尝试使用可选链访问它的 price 属性:

1
2
let car: Car? = Car(model: "BMW")
let price = car?.price

如果 car 实例为空,那么 price 的值将是 nil。否则,它将包含 price 属性的值,该属性本身也是一个可选类型。

访问下标

与访问属性和调用方法类似,我们也可以使用可选链来访问下标。假设我们有一个名为 matrix 的二维数组,我们可以使用可选链来访问数组元素:

1
2
var matrix: [[Int]]?
let x = matrix?[0][0]

如果 matrix 为空,那么 x 的值将是 nil。如果 matrix 不为空,但是第一个子数组为空,那么依然会返回 nil。

链接多层可选链

当我们需要链接多个可选链时,我们可以使用多个问号(??)来链接它们。例如:

1
let price = car?.manufacturer?.address?.location?.latitude ?? 0.0

在这个例子中,我们链接了多个可选链来访问 car 实例的制造商的地址的位置纬度。如果任何一个链接为空,那么整个表达式将返回默认值 0.0。

忽略可选链

如果我们确定一个可选链一定不为空,可以使用感叹号(!)来忽略它的可选性。这被称为强制解包。

例如,假设我们有一个非空的字符串数组:

1
let names = ["Alice", "Bob", "Charlie”]

然后我们可以使用可选链来获取第一个元素的首字母:

1
let firstInitial = names.first?.prefix(1)

在这种情况下,first 的返回类型是 String?,因此 prefix(_:) 方法也返回了一个可选类型的 Substring?。但是,由于我们已经知道 names 数组中至少有一个元素,所以我们可以使用强制解包来忽略这些可选性:

1
let firstInitial = names.first!.prefix(1)!

这里需要注意的是,如果我们错误地对空数组进行强制解包,程序会崩溃并抛出一个运行时错误。

可选链和隐式拆包可选类型

Swift 中还有一种叫做隐式拆包可选类型的类型。这些类型类似于可选类型,但是在访问它们的成员时可以省略问号,因为编译器自动将其解包。

在使用可选链时,隐式拆包可选类型表现得就像普通的可选类型一样。如果我们在可选链中访问隐式拆包可选类型的属性或方法,它仍然可能为空,并且仍然需要使用问号来避免程序崩溃。

以下是一个使用隐式拆包可选类型的示例:

1
2
let label: UILabel! = UILabel()
let text = label?.text

在这个例子中,label 是一个隐式拆包可选类型,它的 text 属性也是一个可选类型。如果 label 为空,则 text 的值将是 nil。

本文由作者按照 CC BY 4.0 进行授权

Swift中的反初始化

Swift中的错误处理