美文网首页
15-Swift可空链式调用

15-Swift可空链式调用

作者: 王梓懿_1fbc | 来源:发表于2018-10-20 22:44 被阅读5次

    可空链式调用是一种可以请求和调用属性、方法以及下标的过程,它的可空体现在请求或调用的目标当前可能为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.residence为nil,在设置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环境

    作者:西门奄
    链接:https://www.jianshu.com/u/77035eb804c3
    來源:简书
    简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

    相关文章

      网友评论

          本文标题:15-Swift可空链式调用

          本文链接:https://www.haomeiwen.com/subject/azcvzftx.html