swift 可选链式调用

Swift 链式语法应用 该文档来自MDCC 2016中国移动开发者大会。陈乘方发表了题为“Swift 链式语法应用”的主题演讲,欢迎下载! 立即下载

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

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

通过在想调用的属性,方法,或下标的可选值后面放一个问号,可以定义一个可选链。这一点很像在可选值后放一个叹号来强制展开它的值。他们主要区别在于当可选值为空时可选链式调用只会调用失败,然而强制展开将触发运行时错误。
为了反映可选链式调用可以在空值上调用的事实,不论这个调用的属性,方法及下标返回的值是不是可选值,它的返回结果都是一个可选值。可以利用这个返回值来判断你的可选链式调用是否调用成功,如果调用有返回值则说明调用成功,返回nil则说明调用失败。
特别的,可选链式调用的返回结果与原本的返回结果具有相同的类型,但是被包装成了一个可选值,例如,使用可选链式调用访问属性,当可选链式调用成功时,如果属性原本返回结果是Int类型,则会变为Int?类型。
    class Person {
        var residence:Residence?
    }
    
    class Residence {
        var numberOfRooms = 1
    }
假如创建一个新的Person实例,它的residence属性由于是可选类型而将初始化为nil,在下面的代码中,John有一个值为nil的residence属性:
 let john = Person()
如果使用叹号强制展开获得这个john的residence属性中的numberOfRooms值,就会触发运行时的错误,因为这时residence没有可以展开的值:
  let roomCount = john.residence!.numberOfRooms
john.residence为非nil值的时候,上面的调用会成功,并且把roomCount设置为Int类型的房间数量。正如上面提到的,当residence为nil的时候上面这段代码会触发运行时错误。
可选链式调用提供了另一种访问numberOfRooms的方式,使用问号来替代感叹号:
  if let roonCount = john.residence?.numberOfRooms {
            
        }else{
            
        }
在residence后面添加问号之后,swift就会在residence不为nil的情况下访问numberOfRooms。
因为访问numberOfRooms有可能失败,可选链式调用会返回Int?类型,或称为“可选的Int”。如上例所示,当residence为nil的时候,可选的Int将会Wienil,表明无法访问numberOfRooms。访问成功时,可选的Int值会通过可选绑定展开,并赋值给可选类型的roomCount常量。
要注意的是,即使numberOfRooms是非可选的Int时,这一点也成立。只要使用可选链式调用就意味着numberOfRooms会返回yigeInt?而不是Int。
将一个residence的实例赋给john.residence,这样它就不再是nil了:
john.residence = Residence()

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

通过使用可选链式调用可以调用多层属性、方法和下标。这样可以在复杂的模型中向下访问各种子属性,并且判断能否访问子属性的属性。方法或下标。
Person类的定义基本保持不变:
  class Person {
        var residence:Residence?
    }
Residence类比之前复杂些,增加了一个名为rooms的变量属性,该属性被初始化为[Room]类型的空数组:
    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?
    }

现在Residence有了一个存储Room实例的数组,numberOfRooms属性被实现为计算型属性,而不是存储型属性。numberOfRooms属性简单地返回rooms数组的count属性的值。

Residence还提供了访问rooms数组的快捷方式,即提供可读写的下标来访问rooms数组中指定位置的元素。此外,Residence还提供了printNumberOfRooms方法,这个方法的作用是打印numberOfRooms的值。
最后,
Residence还定义了一个可选属性address,其类型为Address?。Address类的定义在下面会说明。

Room类是一个简单类,其实例被存储在rooms数组中。该类只包含一个属性name,以及一个用于将该属性设置为适当的房间名的初始化函数: 

class Room {
    let name: String
    init(name: String) { self.name = name }
}

最后一个类是Address,这个类有三个String?类型的可选属性。buildingName以及buildingNumber属性分别表示某个大厦的名称和号码,第三个属性street表示大厦所在街道的名称: 

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.")
}

因为john.residence为nil,所以这个可选链式调用依旧会像先前一样失败。 

let someAddress = Address()
someAddress.buildingNumber = "29"
someAddress.street = "Acacia Road"
john.residence?.address = someAddress

在这个例子中,通过john.residence来设定address属性也会失败,因为john.residence当前为nil。

上面代码中的赋值过程是可选链式调用的一部分,这意味着可选链式调用失败时,等号右侧的代码不会被执行。对于上面的代码来说,很难验证这一点,因为像这样赋值一个常量没有任何副作用。下面的代码完成了同样的事情,但是它使用一个函数来创建Address实例,然后将该实例返回用于赋值。该函数会在返回前打印“Function was called”,这使你能验证等号右侧的代码是否被执行。 

func createAddress() -> Address {
    print("Function was called.")
    let someAddress = Address()
    someAddress.buildingNumber = "29"
    someAddress.street = "Acacia Road"
    return someAddress
}
john.residence?.address = createAddress()

没有任何打印消息,可以看出createAddress()函数并未被执行。 

通过可选链式调用调用方法

可以通过可选链式调用来调用方法,并判断是否调用成功,即使这个方法没有返回值。Residence类中的printNumberOfRooms()方法打印当前的numberOfRooms值,如下所示: 

func printNumberOfRooms() {
    print("The number of rooms is \(numberOfRooms)")
}

如果在可选值上通过可选链式调用来调用这个方法,该方法的返回类型会是Void?,而不是Void,因为通过可选链式调用得到的返回值都是可选的。这样我们就可以使用if语句来判断能否成功调用printNumberOfRooms()方法,即使方法本身没有定义返回值。通过判断返回值是否为nil可以判断调用是否成功: 

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.")
}

我们尝试给john.residence中的address属性赋值,即使residence为nil。通过可选链式调用给属性赋值会返回Void?,通过判断返回值是否为nil就可以知道赋值是否成功: 

if (john.residence?.address = someAddress) != nil {
    print("It was possible to set the address.")
} else {
    print("It was not possible to set the address.")
}

通过可选链式调用访问下标

下面这个例子用下标访问john.residence属性存储的Residence实例的rooms数组中的第一个房间的名称,因为john.residence为nil,所以下标调用失败了: 

if let firstRoomName = john.residence?[0].name {
    print("The first room name is \(firstRoomName).")
} else {
    print("Unable to retrieve the first room name.")
}

在这个例子中,问号直接放在john.residence的后面,并且在方括号的前面,因为john.residence是可选值。类似的,可以通过下标,用可选链式调用来赋值: 

john.residence?[0] = Room(name: "Bathroom")

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

如果你创建一个Residence实例,并为其rooms数组添加一些Room实例,然后将Residence实例赋值给john.residence ,那就可以通过可选链和下标来访问数组中的元素: 

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.")
}

访问可选类型的下标

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

 var testScores = ["Dave": [86, 82, 84], "Bev": [79, 94, 81]]
 testScores["Dave"]?[0] = 91
 testScores["Bev"]?[0] += 1
 testScores["Brian"]?[0] = 72
前两个调用可以成功,但是在字典中没有“Brian”这个键,所以第三个调用失败。

连接多层可选链式调用

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

也就是说:

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

因此: 

• 通过可选链式调用访问一个 Int 值,将会返回 Int? ,无论使用了多少层可选链式调用。• 类似的,通过可选链式调用访问 Int? 值,依旧会返回 Int? 值,并不会返回 Int?? 。

下面的例子尝试访问 john 中的 residence 属性中的 address 属性中的 street 属性。这里使用了两层可选链式调用, residence 以及 address 都是可选值: 

 if let johnsStreet = john.residence?.address?.street {
     print("John's street name is \(johnsStreet).")
 } else {
     print("Unable to retrieve the address.")
}

john.residence 现在包含一个有效的 Residence 实例。然而, john.residence.address 的值当前为 nil 。因此,调用 john.residence?.address?.street 会失败。

需要注意的是,上面的例子中, street 的属性为 String? 。 john.residence?.address?.street 的返回值也依然是 String? ,即使已经使用了两层可选链式调用。

如果为 john.residence.address 赋值一个 Address 实例,并且为 address 中的 street 属性设置一个有效值,我们就能过通过可选链式调用来访问 street 属性: 

 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.")
}

在方法的可选返回值上进行可选链式调用

上面的例子展示了如何在一个可选值上通过可选链式调用来获取它的属性值。我们还可以在一个可选值上通过可
选链式调用来调用方法,并且可以根据需要继续在方法的可选返回值上进行可选链式调用。

在下面的例子中,通过可选链式调用来调用 Address 的 buildingIdentifier() 方法。这个方法返回 String? 类型的值。如上所述,通过可选链式调用来调用该方法,最终的返回值依旧会是 String? 类型: 

if let buildingIdentifier = john.residence?.address?.buildingIdentifier() {
    print("John's building identifier is \(buildingIdentifier).")
}
如果要在该方法的返回值上进行可选链式调用,在方法的圆括号后面加上问号即可:
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\".")
} }

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\".")

}} 



选自《the swift programming language》中文版

swift-YQChainTaskSwift链式调用50行不到代码实现的链式任务调用 YQChainTask:Swift链式调用,50行不到代码实现 的 链式任务调用 立即下载

相关推荐

swift-使用类似Masonry链式编程的方式初始化UIViewUIButtonUILabel等

使用类似Masonry链式编程的方式初始化UIView、UIButton、UILabel、UIScrollview、UITextView、UITabelView

Swift链式编程

链式编程思想简述,swift项目实现链式UI代码

Heyuan_Xie的博客 568

swift-链式封装的UI工具集使用方法类似Masonry与SDAutolayout

加速开发之用点来写UI:链式封装的UI工具集,使用方法类似Masonry与SDAutolayout。

Swift 可选链式调用

通过使用可选链式调用可以调用多层属性、方法和下标。这样可以在复杂的模型中向下访问各种子属性,并且判断能否访问子属性的属性、方法和下标。下面这段代码定义了四个模型类,这些例子包括多层可选链式调用。为了方便说明,在Person和Residence的基础上增加了Room类和Address类,以及相关的属性、方法以及下标。PersonResidence类比之前复杂些,增加了一个名为rooms的变量属性,该属性被初始化为[Room]get {set {现在Residence有了一个存储Room实例的数组,

xiaoxiaobukuang的专栏 743

swift-Maker是一个使用链式语法实现UIKit控件的Category

Maker 是一个使用链式语法实现UIKit控件的Category,快速开发,代码量少,使用方便

Flink实战项目——城市交通实时监控平台

本项目是与公安交通管理综合应用平台、机动车缉查布控系统等对接的,并且基于交通部门现有的数据平台上,进行的数据实时分析项目。

yangwei2048的博客 836

swift学习笔记之-可选链式调用

//可选链式调用 import UIKit /*可选链式调用(Optional Chaining) 1.在可选值上请求和调用该可选值的属性、方法及下标的方法,如果可选值有值,那么调用就会成功,返回可选类型值,如果可选值是nil,那么调用将返回nil,多个调用可以连接在一起形成一个调用链,如果其中任何一个节点为nil,整个调用链都会失败,即返回nil;(而强制展开它的值是"...

weixin_30457551的博客 174

详细推导波特图增益和相位曲线

文章来源:https://mp.weixin.qq.com/s/UCy9mRRok5Hc9qHq3qde5g 今天这篇文章想把近段时间关于波特图方面学习的内容整理一下。波特图将会是梳理闭环控制这个系列的开始。目前的计划是,以无源器件为基础,然后结合运放,再过渡到开关电源的环路控制方面。如果对这方面感兴趣的朋友,可以持续一起学习起来,目标就是掌握开关电源的闭环控制。 1. 什么是波特图? 波特图最常见的应用是在线性非时变的系统中,用于对传递函数的增益和相位进行分析,从而判断出系统随频率的响应是否稳定。因此,波

ltqdxl的博客 2万+

iOS开发Swift开发UI页面链式调用库推荐

【代码】iOS开发Swift开发声明式 UI

滴水成川 975

Java 简易版 UDP 多人聊天室

【代码】Java 简易版 UDP 多人聊天室。

nmy15570188135的博客 1187

基于FPGA的函数信号发生器设计

设计采用波形查找表和相位累加器的方法实现DDS,查找表的数据位宽为8位,采样点数为4096。波形产生范围是100Hz-20MHz,最小频率间隔为1Hz,用8个数码管显示频率,可产生正弦波、方波、三角波,波形用两个led显示,select信号控制,全灭为正弦波,一亮一灭为方波,全亮为锯齿波。为了使频率和相位便于调节,用3个拨码开关控制步进,用8个led显示状态。

FPGA入门到跑路 5633

Swift可选链式调用

可选链式调用是一种可以在当前值可能为nil的可选值上请求和调用属性、方法及下标的方法。如果可选值有值,那么调用就会成功;如果可选值是nil,那么调用将返回nil。多个调用可以连接在一起形成一个调用链,如果其中任何一个节点为nil,整个调用链都会失败,即返回nil。 注意 Swift 的可选链式调用和 Objective-C 中向nil发送消息有些相像,但是 Swift 的可选链式调用可以应用于任...

weixin_34195364的博客 133

别再到处找模型了!手把手教你用Xinference+Docker部署本地私有大模型(Llama2/Qwen实战)

本文详细介绍了如何使用Xinference和Docker部署本地私有化大模型(如Llama2/Qwen),涵盖硬件配置、模型管理、Docker部署及性能优化等关键步骤。通过实战案例,帮助开发者快速构建企业级AI推理服务,确保数据安全与高效运行。

weixin_28683065的博客 231

swift可选链式调用

2.17可选链式调用 本页包含内容: 使用可选链式调用代替强制展开 为可选链式调用定义模型类 通过可选链式调用访问属性 通过可选链式调用调用方法 通过可选链式调用访问下标 连接多层可选链式调用 在方法的可选返回值上进行可选链式调用 可选链式调用是一种可以在当前值可能为nil的可选值上请求和调用属性、方法及下标的方法。如果可选值有值,那么调用就会成功;如果可选值是nil,那么调用将返...

文艺范的博客 358

应急响应-勒索病毒典型处置案例

服务器感染Globelmposter勒索病毒 事件背景 2020年5月,某公司内外服务器遭遇勒索病毒攻击,应急响应工程师在抵达现场后,对包含服务器在内的13太机器进行系统排查和日志分析。 事件处置 勒索病毒初步判定 首先,对其中一台感染勒索病毒的主机A(源地址为192.168.111.129)进行排查,通过勒索信确认为GlobeImposter勒索病毒,如图所示。 在本地桌面及磁盘发现加密文件后缀为.RESERVE,如图所示。 系统排查 主机账号 通过

qq_50765147的博客 2458

CelebA-HQ数据集下载【详细明了版】分辨率包括【64,128,256,512,1024】

CelebA-HQ 是在ICLR2018上,nVidia发表了一篇名为Progressive Growing of GANs for Improved Quality, Stability, and Variation的论文,文中通过训练高分辨率GAN生成了一个新的人脸数据集CelebA-HQ.CelebA是港科大汤晓鸥组收集的人脸数据集(总共200k图片),包括了人脸特征点(landmark),人脸属性(attribute)等信息,详细介绍参考链接[1]和[2]

zik的博客 1万+

Swift学习笔记 (二十六) 可选链式调用

可选链式调用是一种可以在当前值可能为nil的可选值上请求和调用属性、方法及下标的方法。如果可选值有值,那么调用就会 成功;如果可选值是nil,那么调用将返回nil。多个调用可以连接在一起形成一个调用链,如果其中任何一个节点为nil,整个调 用链都会失败,即返回nil。 注意 Swift 的可选链式调用和 Objective-C 中向nil发送消息有些相像,但是...

sjl51060的专栏 253

北斗导航 | SPP、RTK、RTD、PPP-RTK、PPP算法原理,公式及完整matlab代码

开发参考:SPP适合入门学习GNSS定位原理和最小二乘。RTK是工程高精度定位主流方案,但依赖基站。PPP适合无基站区域的广域高精度应用。PPP-RTK是融合两者优点的新一代技术,但系统复杂度最高。· 代码资源:raPPPid(VieVS PPP)是功能完整的MATLAB开源PPP工具箱,支持多系统PPP-AR。MATLAB GPS Toolbox 提供从SPP到PPP的完整功能实现。· 实际应用:农业自动驾驶、无人机航测通常使用网络RTK;大地测量、地壳形变监测常采用PPP事后处理;

尘世冰封的专栏 822

Swift学习:可选链式调用

  可选链式调用是一种可以在当前值可能为 nil 的可选值上请求和调用属性、方法及下标的方法。如果可选值有值,那么调用就会成功;如果可选值是 nil,那么调用将返回 nil。多个调用可以连接在一起形成一个调用链,如果其中任何一个节点为 nil,整个调用链都会失败,即返回 nil。   注意   swift 的可选链式调用和 Objective-C 中向 nil 发送消息有些相像,但是swift...

weixin_30675247的博客 146

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

对照Java学习Swift--可选链式调用(Optional Chaining)

可选链式调用(Optional Chaining)是一种可以在当前值可能为nil的可选值上请求和调用属性、方法及下标的方法。如果可选值有值,那么调用就会成功;如果可选值是nil,那么调用将返回nil。多个调用可以连接在一起形成一个调用链,如果其中任何一个节点为nil,整个调用链都会失败,即返回nil。swift这个功能设计的很好,不会报空指针异常,如果是在Java中,那个环节的对象为空,则报空指针异

谁与争锋的专栏 4370

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

Java可选链_对照Java学习Swift--可选链式调用(Optional Chaining)

可选链式调用(Optional Chaining)是一种可以在当前值可能为nil的可选值上请求和调用属性、方法及下标的方法。如果可选值有值,那么调用就会成功;如果可选值是nil,那么调用将返回nil。多个调用可以连接在一起形成一个调用链,如果其中任何一个节点为nil,整个调用链都会失败,即返回nil。swift这个功能设计的很好,不会报空指针异常,如果是在Java中,那个环节的对象为空,则报空指针...

weixin_36105232的博客 354

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

IOS11,Swift4从入门到精通-19可选链式调用

本节内容转载于 http://www.swift51.com/swift4.0/chapter2/17_Optional_Chaining.html 本页包含内容: 使用可选链式调用代替强制展开 为可选链式调用定义模型类 通过可选链式调用访问属性 通过可选链式调用调用方法 通过可选链式调用访问下标 连接多层可选链式调用 在方法的可选返回值上进行可选链式调用 可选链式调用是一种可以在当前值可能为ni...

liu_jiuyang的博客 265
上一篇: swift 错误处理
下一篇: ios 取得当前界面方法
ChasingDreamsCoder
博客等级 码龄10年 5粉丝 85原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值