多个可选类型组合在一起调用就会形成可选链条。
一、可选链(Optional Chaining)
1.1. 什么是可选链
示例代码:
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 { 30 }
func eat() { print("Person eat") }
subscript(index: Int) -> Int { index }
}
正常调用:
var person: Person = Person()
person.name = "idbeny"
person.age()
- 如果把
person
对象修改为可选类型: - 系统提示要想用可选类型对象引用成员必须强制解包或添加
?
: - 按照提示修改代码,编译通过:
var person: Person? = Person()
var age = person?.age()
var age1 = person!.age()
var name = person!.name = "idbeny"
var index = person?[6]
-
age
是可选类型Int?
,打印Optional(30)
-
age1
是Int
类型,打印18
-
name
是可选类型String?
,打印Optional("idbeny")
-
index
是可选类型Int?
,打印Optional(6)
- 函数返回值:
func getName() -> String { "idbeny" }
person?.name = getName()
如果person
是nil
,就不会调用函数getName()
。
总结:
- 如果可选项为
nil
,调用方法、下标、属性失败,结果为nil
- 如果可选项不为
nil
,调用方法、下标、属性成功,结果会被包装成可选项 - 如果结果本来就是可选项,不会进行再次包装
1.2. 可选项绑定
对象调用函数,是可以用一个变量去接受的,即使函数没有返回值:
var result = person?.eat()
result
是什么呢?如果person
是nil
,result
就是nil
;如果person
不为nil
,则返回一个空元祖(因为Void
本质就是一个空元祖)。
怎样知道eat
函数是否调用成功?可以使用可选项绑定进行解包判断:
if let _ = person?.eat() {
print("调用成功")
} else {
print("调用失败")
}
1.3. 可选链
多个?
可以链接在一起形成可选链代码:
var dog = person?.dog // Dog?
var weight = person?.dog.weight // Int?
var price = person?.car?.price // Int?
如果链中任何一个节点是nil
,那么整个链就会调用失败。可选链最终返回的都是可选类型(不强制解包的情况下)。
二、可选链应用
示例代码一:
var scores = ["idbeny": [10, 20, 30], "1024星球": [66, 88, 99]]
scores["idbeny"]?[0] = 100
print(scores) // 输出:["idbeny": [100, 20, 30], "1024星球": [66, 88, 99]]
scores["1024星球"]?[2] += 11
print(scores) // 输出:["idbeny": [100, 20, 30], "1024星球": [66, 88, 110]]
scores["test"]?[0] = 666
print(scores) // 输出:["idbeny": [100, 20, 30], "1024星球": [66, 88, 110]]
字典取值都是可选类型,因为key
有可能为nil
。所以字典取值一般加上一个?
,尽量不要使用!
强制解包,防止取出的值是nil
。
示例代码二:
var num1: Int? = 5
num1? = 10 // Optional(10)
var num2: Int? = nil
num2? = 10 // nil
num1? = 10
意思是如果num1
不为nil
,就把10赋值给num1
,并且包装为可选类型。
num2? = 10
意思是如果num2
为nil
,后面的代码就不会执行。
示例代码三:
var dict: [String: (Int, Int) -> Int] = [
"sum": (+),
"diff": (-)
]
var result = dict["sum"]?(10, 20)
print(result) // 输出:Optional(30)
(+)
是把两个参数相加并返回的意思,是编译器的语法糖。字典取值如果是函数,该函数也会被包装成可选类型,所以需要?
调用函数,但是最终函数返回值是可选类型。