这是我参与更文挑战的第18天,活动详情查看: 更文挑战
可选链式调用
- 可选链式调用:在当前值可能为
nil
的情况下,用当前值去获取它的属性、方法及其下标。如果可选值有值,调用就会成功,如果可选值是nil
,调用将返回nil
- 多个调用可以连接在一起形成一个调用链,如果其中任何一个节点为
nil
,整个调用链都会失败,即返回nil
使用可选链式调用代替强制解包
class Student {
var hobby: Hobby?
}
class Hobby {
var run = "run"
}
//创建了一个新的Student实例,它的hobby属性由于是是可选型而将初始化为nil
let stu = Student()
//如果使用叹号`!`强制展开获得这个stu的hobby属性中的run值,会触发运行时错误,因为这时run没有可以展开的值
let hobby = stu.hobby!.run //运行时错误
//stu.hobby为非nil值的时候,上面的调用会成功,并且把run设置为String类型
let hobby = stu.hobby?. run //无报错
为可选链式调用定义模型
通过一个简单模型来示例可选链的使用(可选链式调用访问属性、可选链式调用调用方法、可选链式调用访问下标等等)
class Person {
var residence: Residence?
}
class Residence {
var rooms = [Room]()
var numberOfRooms: Int {
return rooms.count
}
subscript(i: Int) -> Room {
get {
return rooms[i]
}
set {
rooms[i] = newValue
}
}
//此方法未指定返回类型,没有返回类型的函数和方法具有隐式返回类型Void,返回值可以是()或空元组。
func printNumberOfRooms() {
print("The number of rooms is \(numberOfRooms)")
}
var address: Address?
}
class Room {
let name: String
init(name: String) { self.name = name }
}
class Address {
var buildingName: String?
var buildingNumber: String?
var street: String?
func buildingIdentifier() -> String? {
if buildingName != nil {
return buildingName
} else if buildingNumber != nil && street != nil {
return "\(buildingNumber) \(street)"
} else {
return nil
}
}
}
通过可选链式访问属性
-
读取属性
由于 john.residence 是
nil
,这种可选链式调用会失败let john = Person() if let roomCount = john.residence?.numberOfRooms { print("John's residence has \(roomCount) room(s).") } else { print("Unable to retrieve the number of rooms.") } //Unable to retrieve the number of rooms.
-
设置属性
通过 john.residence 来设定 address 属性也会失败,因为 john.residence 当前为
nil
let someAddress = Address() someAddress.buildingNumber = "29" someAddress.street = "Acacia Road" john.residence?.address = someAddress
通过可选链式调用方法
- 可以通过可选链式来调用方法,并判断是否调用成功,即使这个方法没有返回值
- 如果在可选值上通过可选链式来调用这个方法,该方法的返回类型会是
Void?
,而不是Void
,因为通过可选链式调用得到的返回值都是可选的let john = Person() if john.residence?.printNumberOfRooms() != nil { print("It was possible to print the number of rooms.") } else { print("It was not possible to print the number of rooms.") } //It was not possible to print the number of rooms.
通过可选链式访问下标
-
通过可选链式调用,可以在一个可选值上访问下标,并且判断下标调用是否成功
注意:
通过可选链式调用访问可选值的下标时,应该将问号放在下标方括号的前面而不是后面,可选链式调用的问号一般直接跟在可选表达式的后面 -
用下标访问 john.residence 属性存储的 Residence 实例的 rooms 数组中的第一个房间的名称,因为 john.residence 为
nil
,所以下标调用失败let john = Person() if let firstRoomName = john.residence?[0].name { print("The first room name is \(firstRoomName).") } else { print("Unable to retrieve the first room name.") } //Unable to retrieve the first room name.
连接多层可选链式调用
- 如果你访问的值不是可选的,可选链式调用将会返回可选值(eg: 可选链式调用访问一个
Int
值,将会返回Int?
) - 如果你访问的值就是可选的,可选链式调用不会让可选返回值变得“更可选”(可选链式调用访问
Int?
值,依旧会返回Int?
值,并不会返回Int??
)