15-Swift可空链式调用

可空链式调用是一种可以请求和调用属性、方法以及下标的过程,它的可空体现在请求或调用的目标当前可能为nil。如果可空的目标有值,即调用就会成功;如果选择的目标为nil,即调用将返回nil。多个连续的调用可以被链接在一起形成一个调用链,如果其中任何一个节点为nil将导致整个链调用失败。


一、使用可空链式调用来强制展开


可空链的定义,即是在要调用非空的属性、方法、下标的可空值后面添加一个问号即可。特别的,可空链式调用的返回结果与原本的返回结果具有相同的类型,但是被包装成了一个可空类型值,当可空链式调用成功时,一个本该返回Int类型的结果将返回Int?类型。

class Person {
    // 可空属性,类型为Student?
    var student:Student?
}

class Student {
    var name = "xxx"
}

let zhangsan = Person()
// 这是错误的,因为zhangsan.student现在是为`nil`
//let name = zhangsan.student!.name

// 可空链式调用,即是使用`?`来代替`!`
// 即是说,只有当student不为空的时候才访问name
let name1 = zhangsan.student?.name
// 另外`var student:Student?`,如果student是为`nil`,那么返回的name也是可空类型的,虽然在定义的时是`var name = "xxx"`
if name1 == nil {
    print("zhangsan --- Student没有进行实例化,即没有名字")
} else {
    print("zhangsan --- \(name1)")
}

let lisi = Person()
// 注意,只要有作实例化操作,那么lisi.student就不是为`nil`
lisi.student = Student()
let name2 = lisi.student?.name
if name2 == nil {
    print("lisi --- Student没有进行实例化,即没有名字")
} else {
    print("lisi --- \(name2!)")
输出结果:
zhangsan --- Student没有进行实例化,即没有名字
lisi --- xxx


二、为可空链式调用定义模型类


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

// 人类
class Person {
    // 一个人,不一定就有房子,即是可空的
    var residence:Residence?
}

// 房子类
class Residence {
    // 房间数组
    var rooms = [Room]()
    // 房间个数
    var numberOfRoos:Int {
        return rooms.count
    }
    // 下标脚本,下标快捷访问数组rooms
    subscript(i:Int) -> Room {
        get {
            return rooms[i]
        }
        set {
            rooms[i] = newValue
        }
    }
    
    // 打印房子中房间数量函数
    func printNumberOfRooms() {
        print("这个房子有\(numberOfRoos)个房间")
    }
}

// 房间类
class Room {
    let name:String
    init(name:String) {
        self.name = name
    }
}

// 地址类
class Address {
    // 房子建造者的名字,可空属性
    var buildingName:String?
    // 房子建造者的联系方法,可空属性
    var buildingTell:String?
    // 房子所在位置,可空属性
    var street:String?
    
    // 房子建造的相关信息
    func buildingIdentifier() -> String? {
        if buildingName != nil {
            return buildingName
        } else if buildingTell != nil {
            return buildingTell
        } else {
            return nil
        }
    }
}


三、通过可空链式调用来访问属性


根据上面创建的类,实例操作来进行访问对应属性:

// 实例化Person
let endEvent = Person()
// 注意Residence为`nil`,那么可空链式调用失败
if let roomCount = endEvent.residence?.numberOfRoos {
    print("EndEvent房子中有\(roomCount)个房间")
} else {
    print("Residence没有进行实例化操作")
}

// 实例化Address
let guangzhou = Address()
guangzhou.buildingName = "xxx"
guangzhou.street = "体育中心"
guangzhou.buildingTell = "xxx-xxx-xxx"
// 通过可空链式调用来设置属性值
// 但是此时设置是失败的,因为endEvent.residence为空
endEvent.residence?.address = guangzhou
// 打印是为`nil`
print(endEvent.residence?.address?.street)
输出结果:
Residence没有进行实例化操作
nil

从上可以看出,使用可空链式调用的好处,在于虽然endEvent.residencenil,在设置address属性时程序不会崩溃,只是设置会失败。


四、通过可空链式调用来调用方法


Residence类中,有一个printNumberOfRooms方法,是打印房子中房间数量的函数。对于这个函数,其返回值类型是Void。但是如果在可空值上,通过可空链式调用来调用此方法,返回值类型是Void?,而不是Void,因为通过可空链式调用得到的返回值是nil

// 如果有实例操作,那么就会是调用成功,否则是调用失败
//endEvent.residence = Residence()

// 通过返回值是否为`nil`可以判断调用是否成功
if endEvent.residence?.printNumberOfRooms() != nil {
    print("调用成功")
} else {
    print("调用失败")
}


五、通过可空链式调用来访问下标


通过可空链式调用,可以用下标来对可空值进行读写,并可以判断下标调用是否成功。

注意: 当通过可空链式调用访问可空值的下标时,应该将问号放在下标方括号的前面而不是后面。可空链式调用的问号一般直接跟在可空表达式的后面。

endEvent.residence = Residence()
// 追加操作
endEvent.residence?.rooms.append(Room(name: "房间1"))
endEvent.residence?.rooms.append(Room(name: "房间2"))
endEvent.residence?.rooms.append(Room(name: "房间3"))
// 通过可空链式调用来访问下标
if let firstRoomName = endEvent.residence?[0].name {
    print("第一个房间的名字是\(firstRoomName)")
} else {
    print("没有对应房间")
}
输出结果:
第一个房间的名字:房间1
// 访问可空类型的下标
// 字典类型
var dict = ["name":["张三","李四","王五"],
            "age":[18, 20, 23]]

// 用可空链式调用,把"name"数组第一个元素设置为"赵六"
dict["name"]?[0] = "赵六"

// 将"age"数组第一个元素设置为25
dict["age"]?[0] = 25

// 将"test"数组第一个元素设置为"测试",但是字典中不存在关键字为"test"的,所以这个是调用失败
dict["test"]?[0] = "测试"

print(dict)
输出结果:
["age": [25, 20, 23], "name": [赵六, 李四, 王五]]


六、多层链接


可以通过多个链接多个可空链式调用来向下访问属性、方法、下标。但是多层可空链式调用不会添加返回值的可空性,即是:
 - 如果访问的值不是可空的,通过可空链式调用将会可以放可空值。
 - 如果访问的值已经是可空的,通过可空链式调用不会变得"更"可空。

// 多层可空链式调用
let endEvent = Person()
// 实例化Residence(如果没有下实例化,那么可空链式将会调用失败)
endEvent.residence = Residence()
// 实例化Address
let guangzhou = Address()
guangzhou.buildingName = "xxx"
guangzhou.street = "广州 -- 体育中心"
guangzhou.buildingTell = "xxx-xxx-xxx"
endEvent.residence?.address = guangzhou

// `street`属性是`String?`,endEvent.residence?.address?.street返回值是`String?`,即是已经进行了两次可空链式调用
if let myStreet = endEvent.residence?.address?.street {
    print("endEvent的住房地址: \(myStreet)")
} else {
    print("endEvent没有房子")
}
输出结果:
endEvent的住房地址: 广州 -- 体育中心


七、对返回可空值的函数进行链接


除了通过可空链式调用获取可空属性值,也还可以通过可空链式调用来调用返回值为可空的方法。

// 通过可空链式调用来调用`Address`中的`buildingIdentifier()`方法,返回类型是`String?`。
  if let myBuildingIdentifier = endEvent.residence?.address?.buildingIdentifier() {
    print("建造信息: \(myBuildingIdentifier)")
}

注意: 在方法的括号后面加上问号,是因为buildingIdentifier()返回值是可空值,而不是方法本身是可空的!!!


注:xcode7.3环境

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,527评论 5 470
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,314评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,535评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,006评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,961评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,220评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,664评论 3 392
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,351评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,481评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,397评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,443评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,123评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,713评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,801评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,010评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,494评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,075评论 2 341

推荐阅读更多精彩内容