日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Swift傻傻分不清楚系列(三)元组与可选类型

發(fā)布時間:2023/12/13 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Swift傻傻分不清楚系列(三)元组与可选类型 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

本頁包含內(nèi)容:

  • 元組
  • 可選
  • nil
  • if 語句以及強制解析
  • 可選綁定
  • 隱式解析可選類型
  • 錯誤處理
  • 斷言

元組

元組(tuples)把多個值組合成一個復(fù)合值。元組內(nèi)的值可以是任意類型,并不要求是相同類型。

下面這個例子中,(404, "Not Found")是一個描述?HTTP 狀態(tài)碼(HTTP status code)的元組。HTTP 狀態(tài)碼是當(dāng)你請求網(wǎng)頁的時候 web 服務(wù)器返回的一個特殊值。如果你請求的網(wǎng)頁不存在就會返回一個404 Not Found狀態(tài)碼。

let http404Error = (404, "Not Found") // http404Error 的類型是 (Int, String),值是 (404, "Not Found")

(404, "Not Found")元組把一個Int值和一個String值組合起來表示 HTTP 狀態(tài)碼的兩個部分:一個數(shù)字和一個人類可讀的描述。這個元組可以被描述為“一個類型為(Int, String)的元組”。

你可以把任意順序的類型組合成一個元組,這個元組可以包含所有類型。只要你想,你可以創(chuàng)建一個類型為(Int, Int, Int)或者(String, Bool)或者其他任何你想要的組合的元組。

你可以將一個元組的內(nèi)容分解(decompose)成單獨的常量和變量,然后你就可以正常使用它們了:

let (statusCode, statusMessage) = http404Error print("The status code is \(statusCode)") // 輸出 "The status code is 404" print("The status message is \(statusMessage)") // 輸出 "The status message is Not Found"

如果你只需要一部分元組值,分解的時候可以把要忽略的部分用下劃線(_)標(biāo)記:

let (justTheStatusCode, _) = http404Error print("The status code is \(justTheStatusCode)") // 輸出 "The status code is 404"

此外,你還可以通過下標(biāo)來訪問元組中的單個元素,下標(biāo)從零開始:

print("The status code is \(http404Error.0)") // 輸出 "The status code is 404" print("The status message is \(http404Error.1)") // 輸出 "The status message is Not Found"

你可以在定義元組的時候給單個元素命名:

let http200Status = (statusCode: 200, description: "OK")

給元組中的元素命名后,你可以通過名字來獲取這些元素的值:

print("The status code is \(http200Status.statusCode)") // 輸出 "The status code is 200" print("The status message is \(http200Status.description)") // 輸出 "The status message is OK"

作為函數(shù)返回值時,元組非常有用。一個用來獲取網(wǎng)頁的函數(shù)可能會返回一個(Int, String)元組來描述是否獲取成功。和只能返回一個類型的值比較起來,一個包含兩個不同類型值的元組可以讓函數(shù)的返回信息更有用。

注意:
元組在臨時組織值的時候很有用,但是并不適合創(chuàng)建復(fù)雜的數(shù)據(jù)結(jié)構(gòu)。如果你的數(shù)據(jù)結(jié)構(gòu)并不是臨時使用,請使用類或者結(jié)構(gòu)體而不是元組。

可選類型

使用可選類型(optionals)來處理值可能缺失的情況。可選類型表示:

  • 有值,等于 x

或者

  • 沒有值

注意:
C 和 Objective-C 中并沒有可選類型這個概念。最接近的是 Objective-C 中的一個特性,一個方法要不返回一個對象要不返回nil,nil表示“缺少一個合法的對象”。然而,這只對對象起作用——對于結(jié)構(gòu)體,基本的 C 類型或者枚舉類型不起作用。對于這些類型,Objective-C 方法一般會返回一個特殊值(比如NSNotFound)來暗示值缺失。這種方法假設(shè)方法的調(diào)用者知道并記得對特殊值進(jìn)行判斷。然而,Swift 的可選類型可以讓你暗示_任意類型_的值缺失,并不需要一個特殊值。

來看一個例子。Swift 的Int類型有一種構(gòu)造器,作用是將一個String值轉(zhuǎn)換成一個Int值。然而,并不是所有的字符串都可以轉(zhuǎn)換成一個整數(shù)。字符串"123"可以被轉(zhuǎn)換成數(shù)字123,但是字符串"hello, world"不行。

下面的例子使用這種構(gòu)造器來嘗試將一個String轉(zhuǎn)換成Int:

let possibleNumber = "123" let convertedNumber = Int(possibleNumber) // convertedNumber 被推測為類型 "Int?", 或者類型 "optional Int"

因為該構(gòu)造器可能會失敗,所以它返回一個可選類型(optional)Int,而不是一個Int。一個可選的Int被寫作Int?而不是Int。問號暗示包含的值是可選類型,也就是說可能包含Int值也可能不包含值。(不能包含其他任何值比如Bool值或者String值。只能是Int或者什么都沒有。)

nil

你可以給可選變量賦值為nil來表示它沒有值:

var serverResponseCode: Int? = 404 // serverResponseCode 包含一個可選的 Int 值 404 serverResponseCode = nil // serverResponseCode 現(xiàn)在不包含值

注意:
nil不能用于非可選的常量和變量。如果你的代碼中有常量或者變量需要處理值缺失的情況,請把它們聲明成對應(yīng)的可選類型。

如果你聲明一個可選常量或者變量但是沒有賦值,它們會自動被設(shè)置為nil:

var surveyAnswer: String? // surveyAnswer 被自動設(shè)置為 nil

注意:
Swift 的nil和 Objective-C 中的nil并不一樣。在 Objective-C 中,nil是一個指向不存在對象的指針。在 Swift 中,nil不是指針——它是一個確定的值,用來表示值缺失。任何類型的可選狀態(tài)都可以被設(shè)置為nil,不只是對象類型。

if 語句以及強制解析

你可以使用if語句和nil比較來判斷一個可選值是否包含值。你可以使用“相等”(==)或“不等”(!=)來執(zhí)行比較。

如果可選類型有值,它將不等于nil:

if convertedNumber != nil {print("convertedNumber contains some integer value.") } // 輸出 "convertedNumber contains some integer value."

當(dāng)你確定可選類型確實包含值之后,你可以在可選的名字后面加一個感嘆號(!)來獲取值。這個驚嘆號表示“我知道這個可選有值,請使用它。”這被稱為可選值的強制解析(forced unwrapping)

if convertedNumber != nil {print("convertedNumber has an integer value of \(convertedNumber!).") } // 輸出 "convertedNumber has an integer value of 123."

注意:
使用!來獲取一個不存在的可選值會導(dǎo)致運行時錯誤。使用!來強制解析值之前,一定要確定可選包含一個非nil的值。

可選綁定

使用可選綁定(optional binding)來判斷可選類型是否包含值,如果包含就把值賦給一個臨時常量或者變量。可選綁定可以用在if和while語句中,這條語句不僅可以用來判斷可選類型中是否有值,同時可以將可選類型中的值賦給一個常量或者變量。

像下面這樣在if語句中寫一個可選綁定:

if let constantName = someOptional {statements }

你可以像上面這樣使用可選綁定來重寫possibleNumber這個例子:

if let actualNumber = Int(possibleNumber) {print("\'\(possibleNumber)\' has an integer value of \(actualNumber)") } else {print("\'\(possibleNumber)\' could not be converted to an integer") } // 輸出 "'123' has an integer value of 123"

這段代碼可以被理解為:

“如果Int(possibleNumber)返回的可選Int包含一個值,創(chuàng)建一個叫做actualNumber的新常量并將可選包含的值賦給它。”

如果轉(zhuǎn)換成功,actualNumber常量可以在if語句的第一個分支中使用。它已經(jīng)被可選類型?包含的?值初始化過,所以不需要再使用!后綴來獲取它的值。在這個例子中,actualNumber只被用來輸出轉(zhuǎn)換結(jié)果。

你可以在可選綁定中使用常量和變量。如果你想在if語句的第一個分支中操作actualNumber的值,你可以改成if var actualNumber,這樣可選類型包含的值就會被賦給一個變量而非常量。

你可以包含多個可選綁定在if語句中,并使用where子句做布爾值判斷。

if let firstNumber = Int("4"), secondNumber = Int("42") where firstNumber < secondNumber {print("\(firstNumber) < \(secondNumber)") } // prints "4 < 42"

隱式解析可選類型

如上所述,可選類型暗示了常量或者變量可以“沒有值”。可選可以通過if語句來判斷是否有值,如果有值的話可以通過可選綁定來解析值。

有時候在程序架構(gòu)中,第一次被賦值之后,可以確定一個可選類型_總會_有值。在這種情況下,每次都要判斷和解析可選值是非常低效的,因為可以確定它總會有值。

這種類型的可選狀態(tài)被定義為隱式解析可選類型(implicitly unwrapped optionals)。把想要用作可選的類型的后面的問號(String?)改成感嘆號(String!)來聲明一個隱式解析可選類型。

當(dāng)可選類型被第一次賦值之后就可以確定之后一直有值的時候,隱式解析可選類型非常有用。隱式解析可選類型主要被用在 Swift 中類的構(gòu)造過程中,請參考無主引用以及隱式解析可選屬性

一個隱式解析可選類型其實就是一個普通的可選類型,但是可以被當(dāng)做非可選類型來使用,并不需要每次都使用解析來獲取可選值。下面的例子展示了可選類型String和隱式解析可選類型String之間的區(qū)別:

let possibleString: String? = "An optional string." let forcedString: String = possibleString! // 需要驚嘆號來獲取值let assumedString: String! = "An implicitly unwrapped optional string." let implicitString: String = assumedString // 不需要感嘆號

你可以把隱式解析可選類型當(dāng)做一個可以自動解析的可選類型。你要做的只是聲明的時候把感嘆號放到類型的結(jié)尾,而不是每次取值的可選名字的結(jié)尾。

注意:
如果你在隱式解析可選類型沒有值的時候嘗試取值,會觸發(fā)運行時錯誤。和你在沒有值的普通可選類型后面加一個驚嘆號一樣。

你仍然可以把隱式解析可選類型當(dāng)做普通可選類型來判斷它是否包含值:

if assumedString != nil {print(assumedString) } // 輸出 "An implicitly unwrapped optional string."

你也可以在可選綁定中使用隱式解析可選類型來檢查并解析它的值:

if let definiteString = assumedString {print(definiteString) } // 輸出 "An implicitly unwrapped optional string."

注意:
如果一個變量之后可能變成nil的話請不要使用隱式解析可選類型。如果你需要在變量的生命周期中判斷是否是nil的話,請使用普通可選類型。

錯誤處理

你可以使用錯誤處理(error handling)來應(yīng)對程序執(zhí)行中可能會遇到的錯誤條件。

相對于可選中運用值的存在與缺失來表達(dá)函數(shù)的成功與失敗,錯誤處理可以推斷失敗的原因,并傳播至程序的其他部分。

當(dāng)一個函數(shù)遇到錯誤條件,它能報錯。調(diào)用函數(shù)的地方能拋出錯誤消息并合理處理。

func canThrowAnError() throws {// 這個函數(shù)有可能拋出錯誤 }

一個函數(shù)可以通過在聲明中添加throws關(guān)鍵詞來拋出錯誤消息。當(dāng)你的函數(shù)能拋出錯誤消息時, 你應(yīng)該在表達(dá)式中前置try關(guān)鍵詞。

do {try canThrowAnError()// 沒有錯誤消息拋出 } catch {// 有一個錯誤消息拋出 }

一個do語句創(chuàng)建了一個新的包含作用域,使得錯誤能被傳播到一個或多個catch從句。

這里有一個錯誤處理如何用來應(yīng)對不同錯誤條件的例子。

func makeASandwich() throws {// ... }do {try makeASandwich()eatASandwich() } catch Error.OutOfCleanDishes {washDishes() } catch Error.MissingIngredients(let ingredients) {buyGroceries(ingredients) }

在此例中,makeASandwich()(做一個三明治)函數(shù)會拋出一個錯誤消息如果沒有干凈的盤子或者某個原料缺失。因為makeASandwich()拋出錯誤,函數(shù)調(diào)用被包裹在try表達(dá)式中。將函數(shù)包裹在一個do語句中,任何被拋出的錯誤會被傳播到提供的catch從句中。

如果沒有錯誤被拋出,?eatASandwich()函數(shù)會被調(diào)用。如果一個匹配Error.OutOfCleanDishes的錯誤被拋出,washDishes函數(shù)會被調(diào)用。如果一個匹配Error.MissingIngredients的錯誤被拋出,buyGroceries(_:)函數(shù)會被調(diào)用,并且使用catch所捕捉到的關(guān)聯(lián)值[String]作為參數(shù)。

斷言

可選類型可以讓你判斷值是否存在,你可以在代碼中優(yōu)雅地處理值缺失的情況。然而,在某些情況下,如果值缺失或者值并不滿足特定的條件,你的代碼可能沒辦法繼續(xù)執(zhí)行。這時,你可以在你的代碼中觸發(fā)一個斷言(assertion)來結(jié)束代碼運行并通過調(diào)試來找到值缺失的原因。

使用斷言進(jìn)行調(diào)試

斷言會在運行時判斷一個邏輯條件是否為true。從字面意思來說,斷言“斷言”一個條件是否為真。你可以使用斷言來保證在運行其他代碼之前,某些重要的條件已經(jīng)被滿足。如果條件判斷為true,代碼運行會繼續(xù)進(jìn)行;如果條件判斷為false,代碼執(zhí)行結(jié)束,你的應(yīng)用被終止。

如果你的代碼在調(diào)試環(huán)境下觸發(fā)了一個斷言,比如你在 Xcode 中構(gòu)建并運行一個應(yīng)用,你可以清楚地看到不合法的狀態(tài)發(fā)生在哪里并檢查斷言被觸發(fā)時你的應(yīng)用的狀態(tài)。此外,斷言允許你附加一條調(diào)試信息。

你可以使用全局assert(_:_:file:line:)函數(shù)來寫一個斷言。向這個函數(shù)傳入一個結(jié)果為true或者false的表達(dá)式以及一條信息,當(dāng)表達(dá)式的結(jié)果為false的時候這條信息會被顯示:

let age = -3 assert(age >= 0, "A person's age cannot be less than zero") // 因為 age < 0,所以斷言會觸發(fā)

在這個例子中,只有age >= 0為true的時候,即age的值非負(fù)的時候,代碼才會繼續(xù)執(zhí)行。如果age的值是負(fù)數(shù),就像代碼中那樣,age >= 0為false,斷言被觸發(fā),終止應(yīng)用。

如果不需要斷言信息,可以省略,就像這樣:

assert(age >= 0)

注意:
當(dāng)代碼使用優(yōu)化編譯的時候,斷言將會被禁用,例如在 Xcode 中,使用默認(rèn)的 target Release 配置選項來 build 時,斷言會被禁用。

何時使用斷言

當(dāng)條件可能為假時使用斷言,但是最終一定要_保證_條件為真,這樣你的代碼才能繼續(xù)運行。斷言的適用情景:

  • 整數(shù)類型的下標(biāo)索引被傳入一個自定義下標(biāo)實現(xiàn),但是下標(biāo)索引值可能太小或者太大。
  • 需要給函數(shù)傳入一個值,但是非法的值可能導(dǎo)致函數(shù)不能正常執(zhí)行。
  • 一個可選值現(xiàn)在是nil,但是后面的代碼運行需要一個非nil值。

注意:
斷言可能導(dǎo)致你的應(yīng)用終止運行,所以你應(yīng)當(dāng)仔細(xì)設(shè)計你的代碼來讓非法條件不會出現(xiàn)。然而,在你的應(yīng)用發(fā)布之前,有時候非法條件可能出現(xiàn),這時使用斷言可以快速發(fā)現(xiàn)問題。


創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現(xiàn)金大獎

總結(jié)

以上是生活随笔為你收集整理的Swift傻傻分不清楚系列(三)元组与可选类型的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。