/*
? 使用可選鏈式調用代替強制展開
? 為可選鏈式調用定義模型類
? 通過可選鏈式調用訪問屬性
? 通過可選鏈式調用調用方法
? 通過可選鏈式調用訪問下標
? 連接多層可選鏈式調用
? 在方法的可選返回值上進行可選鏈式調用
*/
//可選鏈式調用是一種可以在當前值可能為 nil 的可選值上請求和調用屬性、方法及下標的方法。如果可選值有 值,那么調用就會成功;如果可選值是 nil ,那么調用將返回 nil 。多個調用可以連接在一起形成一個調用 鏈,如果其中任何一個節(jié)點為 nil ,整個調用鏈都會失敗,即返回 nil 。
//使用可選鏈式調用代替強制展開
//通過在想調用的屬性、方法、或下標的可選值后面放一個問號( ? ),可以定義一個可選鏈。這一點很像在可選 值后面放一個嘆號( ! )來強制展開它的值。它們的主要區(qū)別在于當可選值為空時可選鏈式調用只會調用失 敗,然而強制展開將會觸發(fā)運行時錯誤。
//下面幾段代碼將解釋可選鏈式調用和強制展開的不同
class Person {
var residence:Residence?
}
class Residence {
var numberOfRooms = 1
}
//Residence 有一個 Int 類型的屬性 numberOfRooms ,其默認值為 1 。 Person 具有一個可選的 residence 屬 性,其類型為 Residence? 。
//假如你創(chuàng)建了一個新的 Person 實例,它的 residence 屬性由于是是可選型而將初始化為 nil ,在下面的代碼中, jo hn 有一個值為 nil 的 residence 屬性:
let john = Person()
//如果使用嘆號( ! )強制展開獲得這個 john 的 residence 屬性中的 numberOfRooms 值,會觸發(fā)運行時錯誤,因為 這時 residence 沒有可以展開的值:
// let roomCount = john.residence!.numberOfRooms // 這會引發(fā)運行時錯誤
//可選鏈式調用提供了另一種訪問 numberOfRooms 的方式,使用問號( ? )來替代原來的嘆號( ! ):
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.”
//在 residence 后面添加問號之后,Swift 就會在 residence 不為 nil 的情況下訪問 numberOfRooms 。
//因為訪問 numberOfRooms 有可能失敗,可選鏈式調用會返回 Int? 類型,或稱為“可選的 Int ”。如上例所 示,當 residence 為 nil 的時候,可選的 Int 將會為 nil ,表明無法訪問 numberOfRooms 。訪問成功時,可選的Int 值會通過可選綁定展開,并賦值給非可選類型的 roomCount 常量。
// 要注意的是,即使 numberOfRooms 是非可選的 Int 時,這一點也成立。只要使用可選鏈式調用就意味著numberOfRooms 會返回一個 Int? 而不是 Int 。
//可以將一個 Residence 的實例賦給 john.residence ,這樣它就不再是 nil 了:
john.residence = Residence()
//john.residence 現(xiàn)在包含一個實際的 Residence 實例,而不再是 nil 。如果你試圖使用先前的可選鏈式調用訪問 numberOfRooms ,它現(xiàn)在將返回值為 1 的 Int? 類型的值:
if let roomCount = john.residence?.numberOfRooms {
print("John's residence has \(roomCount) room(s).")
}else {
print("Unable to retrieve the number of rooms.")
}
// 打印 “John's residence has 1 room(s).”
//為可選鏈式調用定義模型類
//通過使用可選鏈式調用可以調用多層屬性、方法和下標。這樣可以在復雜的模型中向下訪問各種子屬性,并且判斷能否訪問子屬性的屬性、方法或下標。
//下面這段代碼定義了四個模型類,這些例子包括多層可選鏈式調用。為了方便說明,在 Person 和 Residence 的基 礎上增加了 Room 類和 Address 類,以及相關的屬性、方法以及下標。
//Person1 類的定義基本保持不變:
// Residence 類比之前復雜些,增加了一個名為 rooms 的變量屬性,該屬性被初始化為 [Room] 類型的空數(shù)組:
class Person1 {
var residence:Residence1?
}
class Residence1 {
var rooms:Array<Room>
var numberOfRooms: NSInteger {
return rooms.count
}
subscript(i:NSInteger) -> Room {
get {
return rooms[i]
}
set {
rooms[i] = newValue
}
}
func prinfNumberOfRooms() {
print("The number of rooms is \(numberOfRooms)")
}
var address:Address?
init(rooms:Array<Room> , address: Address?) {
self.rooms = rooms
self.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 buildingName != nil {
return buildingName
}else if buildingNumber != nil && street != nil {
return "\(buildingNumber) \(street)"
}else {
return nil
}
}
}
//下面的代碼創(chuàng)建了一個 Person 實例,然后像之前一樣,嘗試訪問 numberOfRooms 屬性:
//因為 john.residence 為 nil ,所以這個可選鏈式調用依舊會像先前一樣失敗。
let john1 = Person1()
if let roomCount = john1.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"
john1.residence?.address = someAddress
// 在這個例子中,通過 john.residence 來設定 address 屬性也會失敗,因為 john.residence 當前為 nil 。
func createAddress() -> Address {
print("Function was called.")
let someAddress = Address()
someAddress.buildingNumber = "29"
someAddress.street = "Acacia Road"
return someAddress
}
john1.residence?.address = createAddress()
//沒有任何打印消息,可以看出 createAddress() 函數(shù)并未被執(zhí)行。
//通過可選鏈式子調用調用方法
//func prinfNumberOfRooms() {
// print("The number of rooms is \(numberOfRooms)")
//}
//最后通過判斷調用
if john1.residence?.prinfNumberOfRooms() != 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.”
//同樣的,可以據(jù)此判斷通過可選鏈式調用為屬性賦值是否成功
if (john1.residence?.address = someAddress) != nil {
print("It was possible to set the address.")
} else {
print("It was not possible to set the address.")
}
// 打印 “It was not possible to set the address.”
//同樣的,可以據(jù)此判斷通過可選鏈式調用為屬性賦值是否成功。在上面的通過可選鏈式調用訪問屬性.我們嘗試給 john1.residence 中的 address 屬性賦值,即使 residence 為 nil 。通過可選鏈式調用給屬性賦 值會返回 Void? ,通過判斷返回值是否為 nil 就可以知道賦值是否成功:
if let firstRoomName = john1.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.”
//通過可選鏈式調用訪問下標
if let firstRoomName = john1.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.”
//如果創(chuàng)建一個Residence1實例,并為其rooms數(shù)組添加一些Room實例,然后將residence實例賦值給john.residence,那就可以通過可選鏈和下標來訪問數(shù)組
// let johnsHouse = Residence1()
// johnsHouse.rooms.append(Room(name: "Living Room"))
//johnsHouse.rooms.append(Room(name: "Kitchen"))
//john1.residence = johnsHouse
//if let firstRoomName = john1.residence?[0].name {
// print("The first room name is \(firstRoomName).")
//} else {
// print("Unable to retrieve the first room name.")
//}
// 打印 “The first room name is Living Room.”
swift-可選鏈式調用
最后編輯于 :
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。
相關閱讀更多精彩內容
- 概念 所謂可選鏈式調用就如同其名稱那樣可以看成一個個鏈環(huán)聯(lián)接在一起的鏈條。每個鏈節(jié)就是一個獲得可選值的調用(包括通...
- 1、可選鏈式調用:通過點語法調用屬性、方法、下標 // 可選鏈式調用可以在當前值為nil的情況下調用屬性,方法,下...
- Swift 使用自動引用計數(shù)(ARC)機制來跟蹤和管理你的應用程序的內存。通常情況下,Swift 內存管理機制會一...