Swift 学习笔记---Optional Chaning

5 篇文章 0 订阅
这篇博客探讨了Swift中的可选链(Optional Chaining)特性,作为强制解包的替代方案。内容包括如何定义模型类以使用可选链,通过可选链访问属性、调用方法和下标,以及处理多重链级和方法返回值的可选链操作。
摘要由CSDN通过智能技术生成

Optional Chaining

可选链是一个可选变量上调用方法,属性和下标的请求过程的过程。
这个可选变量可能是 nil。如果可选变量包含一个值,那么调用就是
成功的。如果可选变量是 nil,调用将返回 nil。多重查询能够被链
接在一起,如果任何链接在链上是 nil,那么全部都是 nil。

Optional Chaining as an Alternative to Forced Unwrapping

当你调用可选值的属性、方法或者下标的时候,我们可以在可选值后加
?来指定一个可选链。这个和放置!来强制解包是相似的。主要的不同
是可选链失败后会返回 nil,而后者将会触发运行时错误。

对于可选链来说 nil 也可以调用方法等,它永远返回可选值。你能检
查返回值来检验可选链是否调用成功。

下面的例子展示可选链和强制解包的不同


class Person {
    var residence: Residence?
}

class Residence {
    var numberOfRooms = 1
}

let john = Person()
//这将导致一个运行时异常
let roomCount = john.residence!.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."

john.residence = Residence()

//即使 residence 有值任然返回可选值
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)."

Defining Model Classes for Optional Chaining

我们先来定义接个类用于随后的列子。


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 buildingNumber != nil && street != nil {
            return "\(buildingNumber) \(street)"
        } else if buildingName != nil {
            return buildingName
        } else {
            return nil
        }
    }
}

通过可选链访问属性

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.")
}
// Prints "Unable to retrieve the number of rooms."

因为 john.residence 是 nil,所以可选链的调用是失败的

我们可以通过可选链来建立属性值
let someAddress = Address()
someAddress.buildingNumber = "29"
someAddress.street = "Acacia Road"
john.residence?.address = someAddress
但是把 address 赋值给 john.residence 将要失败,因为 john.residence为 nil。
如果 john.residence? = Residence()呢?依然是失败的,因
为可选链发下 residence 没有值会直接返回 nil,这将导致等号右
边不会被执行(防止运行时异常吧)。

通过可选链调用方法

当通过可选链来调用一个方法时,我们可以通过检查返回值来查看调用
是否成功。即使方法没有返回值,我们也应该做这个检查。
Residence 的 printNumberOfRooms()方法
   func printNumberOfRooms() {
    print("The number of rooms is \(numberOfRooms)")
}
这个方法没有指定返回值,但是他仍然有个返回值类型 void,这意着
它会返回()值或者空元组


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.")
}
// Prints "It was not possible to print the number of rooms."

通过可选链来访问下标

当通过可选链来访问下标,我们必须对返回值进行检验调用是否成功。
注意此时我们应该把?放在[]之前。


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

john.residence?[0] = Room(name: "Bathroom")
//这个建立新值的过程也是失败的,因为john.residence?返回nil


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.")
}
// Prints "The first room name is Living Room."
访问下标的可选类型
可选链的?要在可选值的后面。例如 Swift 的 Dictionary 类型
的返回值是可选的因此我们要把?放在返回值之后。


var testScores = ["Dave": [86, 82, 84], "Bev": [79, 94, 81]]
testScores["Dave"]?[0] = 91
testScores["Bev"]?[0] += 1
testScores["Brian"]?[0] = 72
// the "Dave" array is now [91, 82, 84] and the "Bev" array is now [80, 94, 81]

链接多重水平的链

1.如果你尝试访问的值不是可选的,但是在多重可选链中返回值是可选的
2.如果你尝试取回的已经是可选的了,他将依然返回可选值,没有更高层的可选
因此如果你通过一个多重可选链访问一个 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.")
}
// Prints "Unable to retrieve the address."
虽然 john.residence 是有值的,然john.residence.address
是 nil,所以当调用john.residence?.address?.street会失败

对方法的返回值放置可选链

我们可以用可选链调用一个方法,这个方法返回一个可选值,在这个可选值上添加可选链。


if let buildingIdentifier = john.residence?.address?.buildingIdentifier() {
    print("John's building identifier is \(buildingIdentifier).")
}
// Prints "John's building identifier is The Larches."
我们也可以在返回值中添加可选链

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\".")
    }
}
// Prints "John's building identifier begins with "The"."
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值