Swift 可选链

可选链

可选链是一个调用和查询可选属性、方法和下标的过程,它可能为 nil 。如果可选项包含值,属性、方法或者下标的调用成功;如果可选项是 nil ,属性、方法或者下标的调用会返回 nil 。多个查询可以链接在一起,如果链中任何一个节点是 nil ,那么整个链就会得体地失败。

可选链代替强制展开

你可以通过在你希望如果可选项为非 nil 就调用属性、方法或者脚本的可选值后边使用问号( ? )来明确可选链。这和在可选值后放叹号( ! )来强制展开它的值非常类似。主要的区别在于可选链会在可选项为 nil 时得体地失败,而强制展开则在可选项为 nil 时触发运行时错误。

为了显示出可选链可以在 nil 值上调用,可选链调用的结果一定是一个可选值,就算你查询的属性、方法或者下标返回的是非可选值。你可以使用这个可选项返回值来检查可选链调用是成功(返回的可选项包含值),还是由于链中出现了 nil 而导致没有成功(返回的可选值是 nil )。

另外,可选链调用的结果与期望的返回值类型相同,只是包装成了可选项。通常返回 Int 的属性通过可选链后会返回一个 Int? 。

接下来的一些代码片段演示了可选链与强制展开的不同并允许你检查是否成功。

首先,定义两个类, Person 和 Residence :

class Person {
    var residence: Residence?
}
 
class Residence {
    var numberOfRooms = 1
}

Residence 实例有一个 Int 属性叫做 numberOfRooms ,它带有默认值 1 . Person 实例有一个 Residence? 类型的可选 residence 属性。 如果你创建一个新的 Person 实例,得益于可选项的特性,它的 residence 属性会默认初始化为 nil 。下面的代码中, john 拥有值为 nil 的 residence 属性:

let john = Person()

如果你尝试访问这个人的 residence 里的 numberOfRooms 属性,通过在 residence 后放一个叹号来强制展开它的值,你会触发一个运行时错误,因为 residence 根本没有值可以展开:

 let roomCount = john.residence!.numberOfRooms
 print("roomCount:\(roomCount)")

截屏2020-07-24 16.44.27.png

上边的代码会在 john.residence 有一个非 nil 值时成功并且给 roomCount 赋值一个包含合适房间号的 Int 值。总之,这段代码一定会在 residence 为 nil 时触发运行时错误,如同上边展示的那样。

可选链提供另一种访问 numberOfRooms 的方法。要使用可选链,使用问号而不是叹号:

if let roomCount = john.residence?.numberOfRooms {
    print("John's residence has \(roomCount) room(s).")
} else {
    print("Unable to retrieve the number of rooms.")
}
// Prints "Unable to retrieve the number of rooms."

这将会告诉 Swift 把可选 residence 属性“链接”起来并且取回 numberOfRooms 的值,如果 residence 存在的话。

由于尝试访问 numberOfRooms 有失败的潜在可能,可选链尝试返回一个 Int? 类型的值,或者说“可选 Int ”。当 residence 为 nil ,就如同上边的栗子,这个可选 Int 将也会是 nil ,来反映出不能访问 numberOfRooms 这个事实。可选 Int 通过可选绑定来展开整数并赋值非可选值给 roomCount 变量。

注意就算 numberOfRooms 是非可选的 Int 也是适用的。事实上通过可选链查询就意味着对 numberOfRooms 的调用一定会返回 Int? 而不是 Int 。

你可以赋值一个 Residence 实例给 john.residence ,这样它就不会再有 nil 值:

john.residence = Residence()

john.residence 现在包含了实际的 Residence 实例,而不是 nil 。如果你尝试用与之前相同的可选链访问 numberOfRooms ,它就会返回一个 Int? 包含默认 numberOfRooms 值 1 :

if let roomCount = john.residence?.numberOfRooms {
    print("John's residence has \(roomCount) room(s).")
} else {
    print("Unable to retrieve the number of rooms.")
}
// Prints "John's residence has 1 room(s)."

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • ios抓包工具Charles

    简书上已经有很多介绍怎么使用Charles的文章,这里就不搬砖了。 这篇文章主要记录下怎么破解Charles,今天无意发现了一个在线破解的,亲自试过了 可以...

    赵哥窟
  • swift set

    set是一个Set类型的集合,集合中只能出现String类型的数据,如果放入了其他类型,会报错。但是如果没有指定集合中的数据类型,那就没有关系。

    赵哥窟
  • iOS performSelector 实现原理

    因为[self performSelector:@selector(test) withObject:nil afterDelay:.0]实际在runloop里...

    赵哥窟
  • Python搭建FTP服务器

    使用的ftp包:pyftpdlib    pip install pyftpdlib就可以下载安装了

    py3study
  • ajax实现步骤之XMLHttpRequest

    我们现在开发一直在使用ajax或者是axios与后台进行交互,这两个在浏览器工作的时候都是基于XMLHttpRequest,只不过是封装了便于使用。axios ...

    wade
  • 程序人生成长发展中的一些感悟

      做开发几年了,其中经历了一些酸甜苦辣,在这个过程中自己也在不断的调整自己,希望能按指定的目标前进,而不至于因为外界的各种阻力而偏移方 向。同时,也经历过很多...

    用户1289394
  • Asp.Net Web API 2第十二课——Media Formatters媒体格式化器

    阅读本文之前,您也可以到Asp.Net Web API 2 系列导航进行查看 http://www.cnblogs.com/aehyok/p/3446289.h...

    aehyok
  • 腾讯设计师:写给新人的8个进阶建议

    其实在学生时代就已经很明确自己想要从事设计的这条路,从毕业到现在也一直在做设计的工作,所以个人觉得非常幸运可以把兴趣与工作相结合。虽然说兴趣是最好的导师,但是更...

    用户1730674
  • Win基本框架代码

    声明:本文为原创,作者为 对弈,转载时请保留本声明及附带文章链接:http://www.duiyi.xyz/c%e5%ae%9e%e7%8e%b0%e9%9b%...

    对弈
  • 2D图像中点的旋转

    点的逆时针旋转可以看做是以原点为起点的向量绕原点逆时针旋转;更进一步,保持向量不动,让坐标轴顺时针旋转θ。

    bering

扫码关注云+社区

领取腾讯云代金券