//可选链式调用
import UIKit
/*可选链式调用(Optional Chaining)
1.在可选值上请求和调用该可选值的属性、方法及下标的方法,如果可选值有值,那么调用就会成功,返回可选类型值,如果可选值是nil,那么调用将返回nil,多个调用可以连接在一起形成一个调用链,如果其中任何一个节点为nil,整个调用链都会失败,即返回nil;(而强制展开它的值是"!",有值则返回该值,无值则会触发运行时错误)
2.通过在想调用的属性、方法、或下标的可选值(optional value)后面放一个问号"?"
3.可选链式调用返回的是可选类型值,它的返回结果与原本的返回结果具有相同的类型,但是被包装成了一个可选值
访问可选类型的下标:
var testScores = ["Dave": [86, 82, 84], "Bev": [79, 94, 81]]
testScores["Dave"]?[0] = 91
在方法的可选返回值上进行可选链式调用,在方法的圆括号后面加上问号
let beginsWithThe = john.residence?.address?.buildingIdentifier()?.hasPrefix("The")
在方法的圆括号后面加上问号是因为你要在buildingIdentifier()方法的可选返回值上进行可选链式调用,而不是方法本身。
*/
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
}
}
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
}
}
}
let john = Person()
if let roomCount = john.residence?.numberOfRooms { //因为john.residence为nil,调用失败,返回nil
print("John's residence has \(roomCount) room(s).")
} else {
print("Unable to retrieve the number of rooms.")
}
// 打印 “Unable to retrieve the number of rooms.”
let someAddress = Address()
someAddress.buildingNumber = "29"
someAddress.street = "Acacia Road"
john.residence?.address = someAddress //因为john.residence当前为nil,调用失败,等号右侧的代码不会被执行,赋值失败
if john.residence?.printNumberOfRooms() != nil { //调用方法失败,返回nil,如果成功则返回void?
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.”
if (john.residence?.address = someAddress) != nil {
print("It was possible to set the address.")
} else {
print("It was not possible to set the address.")
}
// 打印 “It was not possible to set the address.”
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.”
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.”
john.residence?[0] = Room(name: "Bathroom")
if let johnsStreet = john.residence?.address?.street { //连接多层可选链式调用
print("John's street name is \(johnsStreet).")
} else {
print("Unable to retrieve the address.")
}
// 打印 “Unable to retrieve the address.”
var testScores = ["Dave": [86, 82, 84], "Bev": [79, 94, 81]]
testScores["Dave"]?[0] = 91
testScores["Bev"]?[0]++
testScores["Brian"]?[0] = 72 //testScores字典中没有"Brian"这个键,所以第三个调用失败。
// "Dave" 数组现在是 [91, 82, 84],"Bev" 数组现在是 [80, 94, 81]
if let buildingIdentifier = john.residence?.address?.buildingIdentifier() {
print("John's building identifier is \(buildingIdentifier).")
}
// 打印 “John's building identifier is The Larches.”
if let beginsWithThe =
john.residence?.address?.buildingIdentifier()?.hasPrefix("The") { //在方法的可选返回值上进行可选链式调用,在方法的圆括号后面加上问号
if beginsWithThe {
print("John's building identifier begins with \"The\".")
} else {
print("John's building identifier does not begin with \"The\".")
}
}
// 打印 “John's building identifier begins with "The".”