Swift

可选链

本文详细介绍了 Swift 中的可选链,包括其基本概念、替代强制解包、模型类定义、访问属性、调用方法、访问下标以及多层链接。

可选链(Optional Chaining)是一种查询和调用当前可能为 nil 的可选属性、方法及下标的过程。如果可选值有值,则调用成功;如果可选值是 nil,则调用返回 nil。多个调用可以连接在一起形成一个链,如果其中任何一个节点为 nil,整个链就会失败,返回 nil

替代强制解包

通过在可选值后放置问号 ? 来调用可选链,这与放置感叹号 ! 进行强制解包不同。强制解包在值为 nil 时会触发运行时错误,而可选链只会返回 nil

class Person {
    var residence: Residence?
}

class Residence {
    var numberOfRooms = 1
}

let john = Person()

// 强制解包会报错,因为 residence 为 nil
// let roomCount = john.residence!.numberOfRooms

// 可选链调用,返回 Int? 类型
if let roomCount = john.residence?.numberOfRooms {
    print("John's residence has \(roomCount) room(s).")
} else {
    print("Unable to retrieve the number of rooms.")
}
// 打印 "Unable to retrieve the number of rooms."

定义模型类

可以使用可选链来调用多层属性、方法和下标。

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 let buildingNumber = buildingNumber, let street = street {
            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.")
}

通过可选链调用方法

可以通过可选链调用方法,并检查方法调用是否成功。即使方法没有返回值,可选链也会返回 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.")
}

通过可选链访问下标

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

多层链接

可以将多个可选链连接在一起,挖掘模型中更深层的属性、方法和下标。

let john = Person()
john.residence = Residence()
john.residence?.address = Address()
john.residence?.address?.street = "Laurel Street"

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

对返回可选值的函数进行链接

如果函数返回一个可选值,可以在函数调用后加上问号来继续链接。

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\".")
    }
}
在 GitHub 上编辑

上次更新于