Optional Chain(可選鏈?zhǔn)秸{(diào)用)

// 可選鏈?zhǔn)秸{(diào)用
//“可選鏈?zhǔn)秸{(diào)用是一種可以在當(dāng)前值可能為nil的可選值上請求和調(diào)用屬性尚蝌、方法及下標(biāo)的方法。如果可選值有值磕蒲,那么調(diào)用就會成功留潦;如果可選值是nil,那么調(diào)用將返回nil辣往。多個調(diào)用可以連接在一起形成一個調(diào)用鏈兔院,如果其中任何一個節(jié)點為nil,整個調(diào)用鏈都會失敗站削,即返回nil坊萝。”
//“Swift 的可選鏈?zhǔn)秸{(diào)用和 Objective-C 中向nil發(fā)送消息有些相像钻哩,但是 Swift 的可選鏈?zhǔn)秸{(diào)用可以應(yīng)用于任意類型屹堰,并且能檢查調(diào)用是否成功”

//1.使用可選鏈?zhǔn)秸{(diào)用代替強(qiáng)制展開
//“通過在想調(diào)用的屬性、方法街氢、或下標(biāo)的可選值后面放一個問號(?)扯键,可以定義一個可選鏈。這一點很像在可選值后面放一個嘆號(!)來強(qiáng)制展開它的值珊肃。它們的主要區(qū)別在于當(dāng)可選值為空時可選鏈?zhǔn)秸{(diào)用只會調(diào)用失敗荣刑,然而強(qiáng)制展開將會觸發(fā)運行時錯誤馅笙。”
//“為了反映可選鏈?zhǔn)秸{(diào)用可以在空值(nil)上調(diào)用的事實厉亏,不論這個調(diào)用的屬性董习、方法及下標(biāo)返回的值是不是可選值,它的返回結(jié)果都是一個可選值爱只。你可以利用這個返回值來判斷你的可選鏈?zhǔn)秸{(diào)用是否調(diào)用成功皿淋,如果調(diào)用有返回值則說明調(diào)用成功,返回nil則說明調(diào)用失敗恬试∥讶ぃ”
//“特別地,可選鏈?zhǔn)秸{(diào)用的返回結(jié)果與原本的返回結(jié)果具有相同的類型训柴,但是被包裝成了一個可選值哑舒。例如,使用可選鏈?zhǔn)秸{(diào)用訪問屬性幻馁,當(dāng)可選鏈?zhǔn)秸{(diào)用成功時洗鸵,如果屬性原本的返回結(jié)果是Int類型,則會變?yōu)镮nt?類型仗嗦”毂酰”

class Person {
    var residence: Residence?
}
class Residence{
    var numberOfRooms = 1
}
let john = Person()
//let roomCount = john.residence!.numberOfRooms
//強(qiáng)制展開值為nil的可選值會報運行時錯誤
if let roomCount = john.residence?.numberOfRooms {
    print("john's residence has \(roomCount) rooms")
}else{
    print("unable to retrieve the number of rooms")
}

//“在residence后面添加問號之后,Swift 就會在residence不為nil的情況下訪問numberOfRooms”
//“因為訪問numberOfRooms有可能失敗儒将,可選鏈?zhǔn)秸{(diào)用會返回Int?類型吏祸,或稱為“可選的 Int”。如上例所示钩蚊,當(dāng)residence為nil的時候,可選的Int將會為nil蹈矮,表明無法訪問numberOfRooms砰逻。訪問成功時,可選的Int值會通過可選綁定展開泛鸟,并賦值給非可選類型的roomCount常量蝠咆。要注意的是,即使numberOfRooms是非可選的Int時北滥,這一點也成立刚操。只要使用可選鏈?zhǔn)秸{(diào)用就意味著numberOfRooms會返回一個Int?而不是Int≡儆螅”

//2. 為可選鏈?zhǔn)秸{(diào)用定義模型類
//“通過使用可選鏈?zhǔn)秸{(diào)用可以調(diào)用多層屬性菊霜、方法和下標(biāo)。這樣可以在復(fù)雜的模型中向下訪問各種子屬性济赎,并且判斷能否訪問子屬性的屬性鉴逞、方法或下標(biāo)记某。”

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
        }
    }
}
class TestResidence {
    var rooms = [Room]()
    var numberOfRoomsd:Int{
        return rooms.count
    }
    subscript(i:Int)->Room{
        get{
            return rooms[i]
        }
        set{
            rooms[i] = newValue
        }
    }
    func printNumberOfRooms(){
        print("the number of rooms is \(numberOfRoomsd)")
    }
    var address:Address?
}
class TestPerson {
    var testResidence : TestResidence?
}

//3. 通過可選鏈?zhǔn)秸{(diào)用訪問屬性

let johntatol = TestPerson()
if let roomCount = johntatol.testResidence?.numberOfRoomsd{
    print("johntatol's testResidence has \(roomCount) rooms")
}else{
    print("unable to retrieve the number of rooms")
}

//可以通過可選鏈?zhǔn)秸{(diào)用來設(shè)置屬性值

let someAddress = Address()
someAddress.buildingNumber = "29"
someAddress.street = "Acacia Road"
johntatol.testResidence?.address = someAddress

//“面代碼中的賦值過程是可選鏈?zhǔn)秸{(diào)用的一部分构捡,這意味著可選鏈?zhǔn)秸{(diào)用失敗時液南,等號右側(cè)的代碼不會被執(zhí)行。對于上面的代碼來說勾徽,很難驗證這一點滑凉,因為像這樣賦值一個常量沒有任何副作用”

func creatAdress()->Address{
    print("Function was called")
    let someAdress = Address()
    someAdress.buildingNumber = "29"
    someAdress.street = "Acacia Road"
    return someAdress
}

johntatol.testResidence?.address = creatAdress()

// 沒有打印,function was called喘帚。說明creatAdress() 沒有被執(zhí)行譬涡。因為testResidence是nil的。

//4. 通過可選鏈?zhǔn)秸{(diào)用調(diào)用方法
//“可以通過可選鏈?zhǔn)秸{(diào)用來調(diào)用方法啥辨,并判斷是否調(diào)用成功涡匀,即使這個方法沒有返回值”
//“沒有返回值的方法具有隱式的返回類型Void,如無返回值函數(shù)中所述溉知。這意味著沒有返回值的方法也會返回()陨瘩,或者說空的元組“如果在可選值上通過可選鏈?zhǔn)秸{(diào)用來調(diào)用這個方法,該方法的返回類型會是Void?级乍,而不是Void舌劳,因為通過可選鏈?zhǔn)秸{(diào)用得到的返回值都是可選的。這樣我們就可以使用if語句來判斷能否成功調(diào)用printNumberOfRooms()方法玫荣,即使方法本身沒有定義返回值甚淡。通過判斷返回值是否為nil可以判斷調(diào)用是否成功”

if johntatol.testResidence?.printNumberOfRooms() != nil {
    print("it was possible to print the rooms")
}else{
    print("it was not possible to print number of rooms")
}
//打印it was not possible to print number of rooms

//同樣,“可以據(jù)此判斷通過可選鏈?zhǔn)秸{(diào)用為屬性賦值是否成功”
if (johntatol.testResidence?.address = someAddress) != nil {
    print("可以賦值屬性")
}else{
    print("不能賦值屬性")
}
//打印不能賦值屬性

// 5. 可選鏈?zhǔn)秸{(diào)用訪問下標(biāo)
//“通過可選鏈?zhǔn)秸{(diào)用捅厂,我們可以在一個可選值上訪問下標(biāo)贯卦,并且判斷下標(biāo)調(diào)用是否成功”
//“注意 通過可選鏈?zhǔn)秸{(diào)用訪問可選值的下標(biāo)時,應(yīng)該將問號放在下標(biāo)方括號的前面而不是后面焙贷∧旄睿可選鏈?zhǔn)秸{(diào)用的問號一般直接跟在可選表達(dá)式的后面”

if let firstRoomName = johntatol.testResidence?[0].name {
    print("\(firstRoomName) 存在")
}else{
    print("不能獲得第一個房間的名字")
}
//打印 不能獲得第一個房間的名字
johntatol.testResidence?[0] = Room(name:"bathroom")
//賦值同樣會失敗,因為testResidence目前是nil
let johnsHouse = TestResidence()
johnsHouse.rooms.append(Room(name:"livingroom"))
johntatol.testResidence = johnsHouse
//可選值賦值不用使用辙芍? 可選值的屬性方法調(diào)用賦值需要用啡彬?
if let anotherRoomName = johntatol.testResidence?[0].name {
    print("賦值成功了,\(anotherRoomName)")
}else{
    print("賦值失敗")
}
//打印 賦值成功了故硅,livingroom

//“如果下標(biāo)返回可選類型值庶灿,比如 Swift 中Dictionary類型的鍵的下標(biāo),可以在下標(biāo)的結(jié)尾括號后面放一個問號來在其可選返回值上進(jìn)行可選鏈?zhǔn)秸{(diào)用:

var testScores = ["dave":[98,90,80],"bev":[70,49,82]]
testScores["dave"]?[0] = 91
testScores["bev"]?[0] += 1
testScores["brian"]?[0] = 75
print("\(testScores)")
//打印 ["bev": [71, 49, 82], "dave": [91, 90, 80]]

//6. 連續(xù)多層的可選鏈?zhǔn)秸{(diào)用
//“可以通過連接多個可選鏈?zhǔn)秸{(diào)用在更深的模型層級中訪問屬性吃衅、方法以及下標(biāo)往踢。然而,多層可選鏈?zhǔn)秸{(diào)用不會增加返回值的可選層級”
/*
“如果你訪問的值不是可選的捐晶,可選鏈?zhǔn)秸{(diào)用將會返回可選值菲语。
如果你訪問的值就是可選的妄辩,可選鏈?zhǔn)秸{(diào)用不會讓可選返回值變得“更可選”。

因此:
通過可選鏈?zhǔn)秸{(diào)用訪問一個Int值山上,將會返回Int?眼耀,無論使用了多少層可選鏈?zhǔn)秸{(diào)用。
類似的佩憾,通過可選鏈?zhǔn)秸{(diào)用訪問Int?值哮伟,依舊會返回Int?值,并不會返回Int??妄帘±慊疲”

*/

if let jhonStress = johntatol.testResidence?.address?.street {
    print("jhon's stress name is \(jhonStress)")
}else{
    print("unable to retrieve the address")
}
let jhonAddress = Address()
jhonAddress.buildingName = "the larches"
jhonAddress.street = "laurel stress"
johntatol.testResidence?.address = jhonAddress
if let jhonstress = johntatol.testResidence?.address?.street {
    print("the stress is \(jhonstress)")
}else{
   print("can't to retrieve")
}
//打印 the stress is laurel stress  賦值成功

//7. “在方法的可選返回值上進(jìn)行可選鏈?zhǔn)秸{(diào)用”
//“我們還可以在一個可選值上通過可選鏈?zhǔn)秸{(diào)用來調(diào)用方法,并且可以根據(jù)需要繼續(xù)在方法的可選返回值上進(jìn)行可選鏈?zhǔn)秸{(diào)用”

if let buildingIdentifier = johntatol.testResidence?.address?.buildingIdentifier() {
    print("johntatol's builing identifier is \(buildingIdentifier)")
}
//打印johntatol's builing identifier is the larches

//“如果要在該方法的返回值上進(jìn)行可選鏈?zhǔn)秸{(diào)用抡驼,在方法的圓括號后面加上問號即可”

if let beginsWithThe = johntatol.testResidence?.address?.buildingIdentifier()?.hasPrefix("The"){
    if beginsWithThe {
        print("jhon's building identifier begins with \"The\"...")
    }else{
        print("jhon's building identifier does not beging with \"The\"...")
    }
}else{
    print("can't reach ,the optional return nil")
}
//打印jhon's building identifier does not beging with "The"...

//“在方法的圓括號后面加上問號是因為你要在buildingIdentifier()方法的可選返回值上進(jìn)行可選鏈?zhǔn)秸{(diào)用鬼廓,而不是方法本身≈旅耍”

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末碎税,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子馏锡,更是在濱河造成了極大的恐慌雷蹂,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,544評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件杯道,死亡現(xiàn)場離奇詭異匪煌,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)党巾,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評論 3 392
  • 文/潘曉璐 我一進(jìn)店門萎庭,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人昧港,你說我怎么就攤上這事擎椰。” “怎么了创肥?”我有些...
    開封第一講書人閱讀 162,764評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長值朋。 經(jīng)常有香客問我叹侄,道長,這世上最難降的妖魔是什么昨登? 我笑而不...
    開封第一講書人閱讀 58,193評論 1 292
  • 正文 為了忘掉前任趾代,我火速辦了婚禮,結(jié)果婚禮上丰辣,老公的妹妹穿的比我還像新娘撒强。我一直安慰自己禽捆,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,216評論 6 388
  • 文/花漫 我一把揭開白布飘哨。 她就那樣靜靜地躺著胚想,像睡著了一般。 火紅的嫁衣襯著肌膚如雪芽隆。 梳的紋絲不亂的頭發(fā)上浊服,一...
    開封第一講書人閱讀 51,182評論 1 299
  • 那天,我揣著相機(jī)與錄音胚吁,去河邊找鬼牙躺。 笑死,一個胖子當(dāng)著我的面吹牛腕扶,可吹牛的內(nèi)容都是我干的孽拷。 我是一名探鬼主播,決...
    沈念sama閱讀 40,063評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼半抱,長吁一口氣:“原來是場噩夢啊……” “哼脓恕!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起代虾,我...
    開封第一講書人閱讀 38,917評論 0 274
  • 序言:老撾萬榮一對情侶失蹤进肯,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后棉磨,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體江掩,經(jīng)...
    沈念sama閱讀 45,329評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,543評論 2 332
  • 正文 我和宋清朗相戀三年乘瓤,在試婚紗的時候發(fā)現(xiàn)自己被綠了环形。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,722評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡衙傀,死狀恐怖抬吟,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情统抬,我是刑警寧澤火本,帶...
    沈念sama閱讀 35,425評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站聪建,受9級特大地震影響钙畔,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜金麸,卻給世界環(huán)境...
    茶點故事閱讀 41,019評論 3 326
  • 文/蒙蒙 一擎析、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧挥下,春花似錦揍魂、人聲如沸桨醋。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,671評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽喜最。三九已至,卻和暖如春步责,著一層夾襖步出監(jiān)牢的瞬間返顺,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,825評論 1 269
  • 我被黑心中介騙來泰國打工蔓肯, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留遂鹊,地道東北人。 一個月前我還...
    沈念sama閱讀 47,729評論 2 368
  • 正文 我出身青樓蔗包,卻偏偏與公主長得像秉扑,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子调限,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,614評論 2 353

推薦閱讀更多精彩內(nèi)容