iT邦幫忙

2022 iThome 鐵人賽

DAY 29
0

今天是倒數最後一天的前夕了,雖然可能看不完基礎語法但是收穫也是頗多,那我們繼續來看。

可選鏈

可選鏈是一種可以在當前值可能為 nil 的狀況下還可以請求和調用屬性、方法及下標方法。如果可選值有值,那麼就調用成功,反之如果是 nil ,那麼就返回 nil 。如果有多個調用連接再一起,其中只要一個環節為 nil 那麼整個調用鏈就會失敗,及回傳 nil。

使用可選鏈代替強制解包

可選值後面可以放 ? 跟 ! 。驚嘆號就是強制解開他的值。他們兩個的差別是一個調用如果為 nil 就會失敗,另一個則是直接觸發運行錯誤。

下面來看官方舉例來解釋可選鏈的方式跟強制解包的不同。

class Person {
    var residence: Residence?
}

class Residence {
    var numberOfRooms = 1
}

照上面的例子來看,如果是驚嘆號的話,因為 numberOfRooms 有一個整數 1 所以不會報錯
如果他是像下面這樣

class Person {
    var residence: Residence!
}

class Residence {
    var numberOfRooms = nil
}

會直接報錯就不會繼續執行了。

為可選鏈定義模型類

你可以通過可選鏈式可以調用多層屬性、方法和下標。這樣可以在複雜的模型中向下訪問各種子屬性,並且判斷能否訪問子屬性的屬性、方法和下標。

來看一下官方的例子

class Person {
    var residence: 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?
}

然後是 Room 的定義

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

還有 Address

class Address {
    var buildingName: String?
    var buildingNumber: String?
    var street: String?
    func buildingIdentifier() -> String? {
        if buildingName != nil {
            return buildingName
        } else if let buildingNumber = buildingNumber, let street = street {
            return "\(buildingNumber) \(street)"
        } else {
            return nil
        }
    }
}

現在 Residence 裡面有存儲 Room 的 Array,numberOfRoom 是計算屬性,會返回 rooms Array 的 count 屬性。

Address 提供了 bulidingIdentifier 方法,返回 String? 。如果 buildingName 有值則返回 buildingName。 如果 buildingNumber 和 street 都有值則發回兩者拼接的字串。否則就返回 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.")
}
// 打印“Unable to retrieve the number of rooms.”

也可以通過訪問屬性來設定屬性值

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

通過可選鏈是調用來調用方法

可以通過可選鏈來調用方法,並判別是否調用成功,即使那個沒有返回值。

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

也可以用另一個方式看回傳值是否為 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.")
}
// 打印“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.")
}
// 打印“Unable to retrieve the first room name.”

因為 john.residence 是 nil 所以失敗。

今天就到這裡了,感謝大家。


上一篇
30天的 iOS 修仙道路 (28)
下一篇
iOS 修仙道路 站穩腳步基礎篇 (30)
系列文
30天的 iOS 修仙道路 站穩腳步基礎篇30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言