可选链
可选链的基本概念
可选链(Optional Chaining)是Swift中一种安全访问可选值的方式,它允许你查询和调用可选值的属性、方法和下标,而不需要显式地解包可选值。 说说我自己对可选链的理解:可选链其实就是可以用一连串的?,如果?前的值为nil,那么这个表达式的执行结果就是nil,不往下执行了。其实和js中基本一样的。还有可选链的返回的一定是可选类型,因为有返回nil 的这种情况,非可选类型不能放nil.
基本特性
- 如果可选项为
nil,调用方法、下标、属性失败,结果为nil - 如果可选项不为
nil,调用方法、下标、属性成功,结果会被包装成可选项 - 如果结果本来就是可选项,不会进行再次包装
可选链的语法
基本语法
// 使用问号(?)进行可选链调用
optionalValue?.property
optionalValue?.method()
optionalValue?[index]
与强制解包的对比
// 强制解包(危险)
let result = optionalValue!.property
// 可选链(安全)
let result = optionalValue?.property
可选链的工作原理
基础示例
class Car {
var price = 0
}
class Dog {
var weight = 0
}
class Person {
var name: String = ""
var dog: Dog = Dog()
var car: Car? = Car()
func age() -> Int {
return 18
}
func eat() {
print("Person eat")
}
subscript(index: Int) -> Int {
return index
}
}
var person: Person? = Person()
方法调用
let age1 = person!.age() // Int (强制解包)
let age2 = person?.age() // Int? (可选链)
属性访问
let name = person?.name // String?
下标访问
let index = person?[6] // Int?
延迟执行特性
func getName() -> String {
return "jack"
}
// 如果person是nil,不会调用getName()
person?.name = getName()
方法调用结果
if let _ = person?.eat() { // ()?
print("eat调用成功")
} else {
print("eat调用失败")
}
可选链的使用场景
1. 嵌套可选值访问
var dog = person?.dog // Dog?
var weight = person?.dog.weight // Int?
var price = person?.car?.price // Int?
2. 多级可选链
多个?可以链接在一起,如果链中任何一个节点是nil,那么整个链就会调用失败。
class Address {
var street: String?
var city: String?
}
class Person {
var address: Address?
}
class Company {
var manager: Person?
}
let company: Company? = Company()
let street = company?.manager?.address?.street // String?
3. 数组和字典的可选链
var scores = ["Jack": [86, 82, 84], "Rose": [79, 94, 81]]
// 安全地访问和修改数组元素
scores["Jack"]?[0] = 100
scores["Rose"]?[2] += 10
scores["Kate"]?[0] = 88 // Kate不存在,操作被忽略
print(scores)
// ["Jack": [100, 82, 84], "Rose": [79, 94, 91]]
4. 可选值的赋值
var num1: Int? = 5
num1? = 10 // Optional(10)
var num2: Int? = nil
num2? = 10 // nil (没有被赋值)
5. 函数可选链
var dict: [String: (Int, Int) -> Int] = [
"sum": (+),
"difference": (-)
]
let result = dict["sum"]?(10, 20) // Optional(30), Int?
let result2 = dict["multiply"]?(10, 20) // nil