博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Swift可选链式调用
阅读量:6858 次
发布时间:2019-06-26

本文共 4551 字,大约阅读时间需要 15 分钟。

可选链式调用是一种可以在当前值可能为nil的可选值上请求和调用属性、方法及下标的方法。如果可选值有值,那么调用就会成功;如果可选值是nil,那么调用将返回nil。多个调用可以连接在一起形成一个调用链,如果其中任何一个节点为nil,整个调用链都会失败,即返回nil

注意 Swift 的可选链式调用和 Objective-C 中向nil发送消息有些相像,但是 Swift 的可选链式调用可以应用于任意类型,并且能检查调用是否成功。

使用可选链式调用代替强制展开

通过在想调用的属性、方法、或下标的可选值后面放一个问号(?),可以定义一个可选链。这一点很像在可选值后面放一个叹号(!)来强制展开它的值。它们的主要区别在于当可选值为空时可选链式调用只会调用失败,然而强制展开将会触发运行时错误。

特别地,可选链式调用的返回结果与原本的返回结果具有相同的类型,但是被包装成了一个可选值。例如,使用可选链式调用访问属性,当可选链式调用成功时,如果属性原本的返回结果是Int类型,则会变为Int?类型。

class Person {    var residence: Residence?}class Residence {    var numberOfRooms = 1}复制代码

可选链式调用提供了另一种访问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.”复制代码

residence后面添加问号之后,Swift 就会在residence不为nil的情况下访问numberOfRooms

为可选链式调用定义模型类

通过使用可选链式调用可以调用多层属性、方法和下标。这样可以在复杂的模型中向下访问各种子属性,并且判断能否访问子属性的属性、方法或下标。

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        }    }}复制代码
通过可选链式调用访问属性

下面的代码创建了一个Person实例,然后像之前一样,尝试访问numberOfRooms属性:

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.”复制代码
通过可选链式调用调用方法

可以通过可选链式调用来调用方法,并判断是否调用成功,即使这个方法没有返回值。

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")复制代码

这次赋值同样会失败,因为residence目前是nil

访问可选类型的下标

如果下标返回可选类型值,比如 Swift 中Dictionary类型的键的下标,可以在下标的结尾括号后面放一个问号来在其可选返回值上进行可选链式调用:

var testScores = ["Dave": [86, 82, 84], "Bev": [79, 94, 81]]testScores["Dave"]?[0] = 91testScores["Bev"]?[0] += 1testScores["Brian"]?[0] = 72// "Dave" 数组现在是 [91, 82, 84],"Bev" 数组现在是 [80, 94, 81]复制代码

上面的例子中定义了一个testScores数组,包含了两个键值对,把String类型的键映射到一个Int值的数组。这个例子用可选链式调用把"Dave"数组中第一个元素设为91,把"Bev"数组的第一个元素+1,然后尝试把"Brian"数组中的第一个元素设为72。前两个调用成功,因为testScores字典中包含"Dave""Bev"这两个键。但是testScores字典中没有"Brian"这个键,所以第三个调用失败。

连接多层可选链式调用

可以通过连接多个可选链式调用在更深的模型层级中访问属性、方法以及下标。然而,多层可选链式调用不会增加返回值的可选层级。

也就是说:

  • 如果你访问的值不是可选的,可选链式调用将会返回可选值。
  • 如果你访问的值就是可选的,可选链式调用不会让可选返回值变得“更可选”。

因此:

  • 通过可选链式调用访问一个Int值,将会返回Int?,无论使用了多少层可选链式调用。
  • 类似的,通过可选链式调用访问Int?值,依旧会返回Int?值,并不会返回Int??
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.”复制代码
在方法的可选返回值上进行可选链式调用

如果要在该方法的返回值上进行可选链式调用,在方法的圆括号后面加上问号即可:

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".”复制代码

注意 在上面的例子中,在方法的圆括号后面加上问号是因为你要在buildingIdentifier()方法的可选返回值上进行可选链式调用,而不是方法本身。

引自:http://www.piggybear.net/?p=699

转载于:https://juejin.im/post/5a312b0ff265da4321540b44

你可能感兴趣的文章
vim 工具(一)
查看>>
MySQL常用命令
查看>>
zabbix snmp监控
查看>>
MySQL单实例重置密码的两种方法
查看>>
一段典型的PHP程序都包含那些内容呢?
查看>>
Windows Phone 7 数据绑定的简单介绍
查看>>
合并下载的Solaris镜像为DVD文件的方法
查看>>
shell编程入门步步高(一、shell简介)
查看>>
一个简单的HQL优化
查看>>
从股价说起 百神大战凸现百度与腾讯阿里差距
查看>>
MariaDB六之主从复制
查看>>
outlook cannot send this item
查看>>
【Win7下Android native code的编译和调试】
查看>>
【iOS-cocos2d-X 游戏开发之十】自定义各类模版&触屏事件讲解!
查看>>
域环境下如何保护重要资料文件的安全(二)---IRM&RMS(下)
查看>>
服务器升迁架构.png
查看>>
不能联系xx域的域控制器
查看>>
生产网络做portfast等配置对网络的影响
查看>>
Connection is read-only. Queries leading to data modification are not allowed
查看>>
LeetCode - 43. Multiply Strings
查看>>