在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
可选链Optional Chaining是一种可以在当前值可能为
通过在想调用的属性、方法、或下标的可选值(optional value)后面放一个问号( 为了反映可选链式调用可以在空值( 特别地,可选链式调用的返回结果与原本的返回结果具有相同的类型,但是被包装成了一个可选值。例如,使用可选链式调用访问属性,当可选链式调用成功时,如果属性原本的返回结果是 下面几段代码将解释可选链式调用和强制展开的不同。 首先定义两个类 class Person { var residence: Residence? } class Residence { var numberOfRooms = 1 }
如果创建一个新的 let john = Person() 如果使用叹号( let roomCount = john.residence!.numberOfRooms // 这会引发运行时错误
可选链式调用提供了另一种访问 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 = Residence()
if let roomCount = john.residence?.numberOfRooms { print("John's residence has \(roomCount) room(s).") } else { print("Unable to retrieve the number of rooms.") } // 打印 “John's residence has 1 room(s).” 为可选链式调用定义模型类通过使用可选链式调用可以调用多层属性、方法和下标。这样可以在复杂的模型中向下访问各种子属性,并且判断能否访问子属性的属性、方法或下标。 下面这段代码定义了四个模型类,这些例子包括多层可选链式调用。为了方便说明,在
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 { 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
在这个例子中,通过 上面代码中的赋值过程是可选链式调用的一部分,这意味着可选链式调用失败时,等号右侧的代码不会被执行。对于上面的代码来说,很难验证这一点,因为像这样赋值一个常量没有任何副作用。下面的代码完成了同样的事情,但是它使用一个函数来创建 func createAddress() -> Address { print("Function was called.") let someAddress = Address() someAddress.buildingNumber = "29" someAddress.street = "Acacia Road" return someAddress } john.residence?.address = createAddress()
没有任何打印消息,可以看出 通过可选链式调用调用方法可以通过可选链式调用来调用方法,并判断是否调用成功,即使这个方法没有返回值。
这个方法没有返回值。然而,没有返回值的方法具有隐式的返回类型 如果在可选值上通过可选链式调用来调用这个方法,该方法的返回类型会是 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.”
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.”
在这个例子中,问号直接放在 类似的,可以通过下标,用可选链式调用来赋值: john.residence?[0] = Room(name: "Bathroom")
这次赋值同样会失败,因为 如果你创建一个 let johnsHouse = Residence() johnsHouse.rooms.append(Room(name: "Living Room")) johnsHouse.rooms.append(Room(name: "Kitchen")) john.residence = johnsHouse if let firstRoomName = john.residence?[0].name { print("The first room name is \(firstRoomName).") } else { print("Unable to retrieve the first room name.") } // 打印 “The first room name is Living Room.”
访问可选类型的下标如果下标返回可选类型值,比如 Swift 中 var testScores = ["Dave": [86, 82, 84], "Bev": [79, 94, 81]] testScores["Dave"]?[0] = 91 testScores["Bev"]?[0]++ testScores["Brian"]?[0] = 72 // "Dave" 数组现在是 [91, 82, 84],"Bev" 数组现在是 [80, 94, 81]
上面的例子中定义了一个 连接多层可选链式调用可以通过连接多个可选链式调用在更深的模型层级中访问属性、方法以及下标。然而,多层可选链式调用不会增加返回值的可选层级。 也就是说:
因此:
下面的例子尝试访问 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.”
需要注意的是,上面的例子中, 如果为 let johnsAddress = Address() johnsAddress.buildingName = "The Larches" johnsAddress.street = "Laurel Street" john.residence?.address = johnsAddress if let johnsStreet = john.residence?.address?.street { print("John's street name is \(johnsStreet).") } else { print("Unable to retrieve the address.") } // 打印 “John's street name is Laurel Street.”
在上面的例子中,因为 在方法的可选返回值上进行可选链式调用上面的例子展示了如何在一个可选值上通过可选链式调用来获取它的属性值。我们还可以在一个可选值上通过可选链式调用来调用方法,并且可以根据需要继续在方法的可选返回值上进行可选链式调用。 在下面的例子中,通过可选链式调用来调用 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".”
|
请发表评论