Swift 5.1 (1) - 基礎(chǔ)

級(jí)別: ★☆☆☆☆
標(biāo)簽:「iOS」「Swift 5.1」「常量變量」「元組」「可選項(xiàng)」「可選綁定」
作者: 沐靈洛
審校: QiShare團(tuán)隊(duì)


常量和變量:常量的值一旦設(shè)置就不能更改,而變量可以在將來(lái)設(shè)置為不同的值。常量和變量必須在使用之前聲明。常量聲明使用let關(guān)鍵字。變量聲明使用var關(guān)鍵字。

let num1 = 10 //!< 聲明一個(gè)常量num1,并且賦初始值10
var num2 = 5  //!< 聲明一個(gè)變量num2,并且賦初始值5
let a = 1, b = 3, c = 4 //!< 同時(shí)聲明多個(gè)常量并賦初值
var aa = 1, bb = 3, cc = 4 //!< 同時(shí)聲明多個(gè)變量并賦初值

類(lèi)型注釋:聲明常量或變量時(shí),可以提供類(lèi)型注釋?zhuān)郧宄A炕蜃兞靠梢源鎯?chǔ)的值的類(lèi)型。通過(guò)在常量或變量名稱后面放置冒號(hào),后跟空格,后跟要使用的類(lèi)型的名稱來(lái)編寫(xiě)類(lèi)型注釋。

let num3 : Int = 3 //!<聲明一個(gè)常量num1,可以存儲(chǔ)的值得類(lèi)型是Int類(lèi)型,并且賦初始值3
var str : String = "QS" //!< 聲明一個(gè)變量str,可以存儲(chǔ)的值得類(lèi)型是String類(lèi)型,并且賦初始值"QS"
let a : Int = 1, b : [Int] = [3,4,5], c : String = "constant" //!< < 同時(shí)聲明,多個(gè)可以存儲(chǔ)不同類(lèi)型值的常量,并賦相應(yīng)類(lèi)型初值
var aa : Int = 1, bb : [Int] = [3,4,5], cc : String = "change" //!< < 同時(shí)聲明,多個(gè)可以存儲(chǔ)不同類(lèi)型值的變量,并賦相應(yīng)類(lèi)型初值

命名規(guī)則:常量和變量名稱幾乎可以包含任何字符,包括Unicode字符。但是常量和變量名稱不能包含空格字符,數(shù)學(xué)符號(hào),箭頭,專(zhuān)用Unicode標(biāo)量值或行和框繪制字符。也不能以數(shù)字開(kāi)頭,但可以包含在名稱的其他地方。使用Swift關(guān)鍵字作為變量名稱時(shí),需要使用``包裹。如下例所示:

let π = 3.14159
let 你好 = "你好世界"
let ???? = "dogcow"
let s2r = "s2r"
let `default` = "default"http://!< 使用Swift關(guān)鍵字作為變量名稱時(shí),需要使用``包裹

一旦聲明了某個(gè)類(lèi)型的常量或變量,就不能再使用相同的名稱聲明它,或者將其更改為存儲(chǔ)不同類(lèi)型的值。也不能將常量變?yōu)樽兞炕蜃兞孔優(yōu)槌A俊?br> 打印方法
print(_:separator:terminator:)它可以將一個(gè)或多個(gè)值輸出到控制臺(tái)。separator和terminator參數(shù)都有默認(rèn)值分別是" "\n,使用時(shí)可以忽略。

let word = "張翼德"
print(word)//!< 控制臺(tái)輸出:張翼德
let p1 = "HOW"
let p2 = "ARE"
let p3 = "YOU?"
print(p1,p2,p3,separator: "...")//!< 控制臺(tái)輸出:HOW...ARE...YOU?
print(p1,p2,p3,separator: ".",terminator: "FINE THANKS\n")//!<控制臺(tái)輸出:HOW.ARE.YOU?FINE THANKS

print(_ separator:terminator:to:)它可以將一個(gè)或多個(gè)值輸出到合適的輸出。separator和terminator參數(shù)都有默認(rèn)值分別是" "\n,使用時(shí)可以忽略。

let p1 = "HOW"
let p2 = "ARE"
let p3 = "YOU?"
var  outputStream = ""
print(p1,p2,p3,separator: ".",terminator: "FINE THANKS\n",to:&outputStream)
print("打印的數(shù)據(jù),寫(xiě)入了outputStream變量中最終輸出為:\(outputStream)")//!< 控制臺(tái)輸出:打印的數(shù)據(jù),寫(xiě)入了outputStream變量中最終輸出為:HOW.ARE.YOU?FINE THANKS

Swift使用字符串插值將常量或變量的名稱包含在較長(zhǎng)字符串中作為占位符,并提示Swift將其替換為該常量或變量的當(dāng)前值。將名稱括在括號(hào)中,并在左括號(hào)前用反斜杠轉(zhuǎn)義它:

let word = "張翼德"
print("我乃燕人\(word)也!誰(shuí)敢與我決一死戰(zhàn)?")

代碼注釋:?jiǎn)涡凶⑨屢詢蓚€(gè)正斜杠開(kāi)頭//。多行注釋以正斜杠開(kāi)頭后跟星號(hào)/*,以星號(hào)后跟正斜杠*/結(jié)束。Swift中的多行注釋可以嵌套在其他多行注釋中。

/* This is the start of the first multiline comment.
 /* This is the second, nested multiline comment. */
This is the end of the first multiline comment. */

分號(hào):Swift不要求代碼中的每個(gè)語(yǔ)句之后都需要加分號(hào);我們可以寫(xiě)也可以不寫(xiě)。如果一行代碼中有多個(gè)語(yǔ)句,則必須要加分號(hào);

整型:沒(méi)有小數(shù)部分,整數(shù)有符號(hào)(正,零或負(fù))或無(wú)符號(hào)(正或零)。Swift提供8,16,32和64位格式的有符號(hào)和無(wú)符號(hào)整數(shù)。這些整數(shù)遵循類(lèi)似于C的命名約定,因?yàn)?位無(wú)符號(hào)整數(shù)屬于類(lèi)型UInt8,32位有符號(hào)整數(shù)屬于類(lèi)型Int32。

整數(shù)邊界:

  1. 不同位數(shù)格式的有符號(hào)和無(wú)符號(hào)整數(shù),都會(huì)有最大值和最小值。
//無(wú)符號(hào)
let unsignedMinValue = UInt8.min  // UInt8類(lèi)型最小值 0
let unsignedMaxValue = UInt8.max  // UInt8類(lèi)型最大值 255
//有符號(hào)
let minValue = Int8.min  // Int8類(lèi)型最小值 -128
let maxValue = Int8.max  // Int8類(lèi)型最大值 127
  1. Swift提供了一個(gè)額外的整數(shù)類(lèi)型Int,它與當(dāng)前平臺(tái)機(jī)器的字節(jié)位數(shù)相同。即:大多數(shù)情況下,我們不需要選擇該使用哪種大小的整數(shù)類(lèi)型。除非我們需要使用特定大小的整數(shù)。每種整數(shù)類(lèi)型存儲(chǔ)不同的值范圍,編譯代碼時(shí),會(huì)檢查是否在指定的整數(shù)類(lèi)型范圍內(nèi)。在不同整數(shù)類(lèi)型的數(shù)值間運(yùn)算時(shí),需要根據(jù)實(shí)際情況進(jìn)行轉(zhuǎn)換。
    • 在32位平臺(tái)上,Int與Int32大小相同。
    • 在64位平臺(tái)上,Int與Int64大小相同。
    • 在32位平臺(tái)上,UInt與UInt32大小相同。
    • 在64位平臺(tái)上,UInt與UInt64大小相同。
let cannotBeNegative: UInt8 = -1 //報(bào)錯(cuò)代碼:無(wú)符號(hào)的8位整數(shù)類(lèi)型不能表示有符號(hào)的-1
let tooBig: Int8 = Int8.max + 1 //報(bào)錯(cuò)代碼:Int8表示范圍0-255 不能表示256報(bào)錯(cuò)
let twoThousand: UInt16 = 2000
let one: UInt8 = 1
let twoThousandAndOne = twoThousand + UInt16(one)

浮點(diǎn)數(shù)字: 浮點(diǎn)數(shù)是具有小數(shù)部分的數(shù)字,浮點(diǎn)類(lèi)型可以表示比整數(shù)類(lèi)型更寬范圍的值。例如3.14159,0.1,和-273.15。Swift提供了兩種帶符號(hào)的浮點(diǎn)數(shù)類(lèi)型:Double 表示64位浮點(diǎn)數(shù)。 Float 表示32位浮點(diǎn)數(shù)。
整數(shù)與浮點(diǎn)數(shù)之間的轉(zhuǎn)換:
整數(shù)轉(zhuǎn)浮點(diǎn)數(shù)

let three = 3 //需要類(lèi)型轉(zhuǎn)換,使用常量three創(chuàng)建一個(gè)double類(lèi)型的新值:Double(three),否則這種相加操作不被允許會(huì)報(bào)錯(cuò)
let pointOneFourOneFiveNine = 0.14159
let pi = Double(three) + pointOneFourOneFiveNine

浮點(diǎn)數(shù)轉(zhuǎn)整數(shù)

let pi = 3.14159
let integerPi = Int(pi)//采用這種形式則浮點(diǎn)數(shù)總是被截?cái)啵@意味著4.76->4 ,3.9->3

類(lèi)型安全和類(lèi)型判斷: Swift是一種類(lèi)型安全的語(yǔ)言,編譯代碼時(shí)執(zhí)行類(lèi)型檢查,并將任何不匹配的類(lèi)型標(biāo)記為錯(cuò)誤,讓我們?cè)陂_(kāi)發(fā)過(guò)程中盡早捕獲并修復(fù)錯(cuò)誤。比如:定義的變量或常量是String類(lèi)型的,那么我們就不能使用Int類(lèi)型賦值。所以Swift鼓勵(lì)我們?cè)谑褂米兞炕虺A繒r(shí),能夠清楚的知道所需的值的類(lèi)型。但并不意味著我們必須指定聲明的變量或常量的類(lèi)型。如果未指定所需的值類(lèi)型,Swift將使用類(lèi)型推斷來(lái)匹配適當(dāng)?shù)念?lèi)型。類(lèi)型推斷使編譯器能夠在編譯代碼時(shí)自動(dòng)推斷出特定表達(dá)式的類(lèi)型,只需檢查我們提供的值即可。類(lèi)型推斷有助于使Swift代碼在使用其類(lèi)型已知的其他值初始化常量或變量時(shí)簡(jiǎn)潔性和可讀性更高。
使用初始值聲明常量或變量時(shí),類(lèi)型推斷特別有用。推斷浮點(diǎn)數(shù)的類(lèi)型時(shí),Swift總是選擇Double(而不是Float)。如let π = 3.14159,π 將會(huì)推斷為Double類(lèi)型。let π = 3 + 0.14159Double類(lèi)型作為加法的一部分,所以也會(huì)推斷為Double類(lèi)型
數(shù)值(浮點(diǎn),整數(shù))類(lèi)型表達(dá)式:

一個(gè)十進(jìn)制數(shù)(decimal),無(wú)前綴
一個(gè)二進(jìn)制數(shù)(binary),有0b前綴
一個(gè)八進(jìn)制數(shù)(octal),有0o前綴
一個(gè)十六進(jìn)制數(shù)(hexadecimal),有0x前綴

一個(gè)整數(shù)17,使用不同進(jìn)制數(shù)進(jìn)行表示

let decimalInteger = 17
let binaryInteger = 0b10001       // 二進(jìn)制數(shù)表示17
let octalInteger = 0o21           // 八進(jìn)制數(shù)表示17 
let hexadecimalInteger = 0x11     // 16進(jìn)制數(shù)表示17

浮點(diǎn)數(shù)可以是沒(méi)有前綴的十進(jìn)制數(shù),或者帶有0x前綴的十六進(jìn)制數(shù),不管是無(wú)前綴的十進(jìn)制數(shù)還是有前綴的十六進(jìn)制數(shù)它們必須始終在小數(shù)點(diǎn)的兩邊都有一個(gè)數(shù)字。(基于此我們可能會(huì)用到表達(dá)式去實(shí)現(xiàn))十進(jìn)制數(shù)有一個(gè)可選的指數(shù),可以使用大寫(xiě)或小寫(xiě)的e來(lái)表示,即:en = 10?,十六進(jìn)制數(shù)也必須會(huì)有一個(gè)可選的指數(shù),可以使用大寫(xiě)或小寫(xiě)的p來(lái)表示,即:pn = 2?.
浮點(diǎn)數(shù)十進(jìn)制數(shù)表示:

1.25e2表示1.25 * 10^2,或125.0。
1.25e-2表示1.25 * 10^ -2,或0.0125。

浮點(diǎn)數(shù)十六進(jìn)制數(shù)表示:

0xFp2指15 * 2^2,或60.0。
0xFp-2表示15 * 2^-2,或3.75。

一個(gè)浮點(diǎn)數(shù)12.1875,可以使用如下表達(dá)式:

let decimalDouble = 12.1875
let exponentDouble = 1.21875e1
let hexadecimalDouble = 0xC.3p0

數(shù)字文字可以包含額外的格式以使其更易于閱讀。整數(shù)和浮點(diǎn)數(shù)都可以用額外的零填充,并且可以包含下劃線以幫助提高可讀性。這兩種格式都不會(huì)影響文字的基礎(chǔ)值:

let paddedDouble = 000123.456
let oneMillion = 1_000_000
let justOverOneMillion = 1_000_000.000_000_1

定義別名:使用關(guān)鍵字:typealias為現(xiàn)有類(lèi)型定義別名。

typealias MyString = String
var my :MyString?
my = "我"
print(my!)

布爾:Swift有一個(gè)基本的布爾類(lèi)型,叫做Bool。Swift只提供了兩個(gè)布爾常量值:truefalse

元組: 元組中的值可以是任何類(lèi)型,并且不必彼此具有相同的類(lèi)型。我們可以創(chuàng)建任意數(shù)量,任何類(lèi)型,任意順序的組合,作為一個(gè)元組。元組作為函數(shù)的返回值特別有用。

let someGrop =  ("元組",401,"未授權(quán)",[1,3],true,["name" : "張三"])
print(someGrop)

分解元組中的常量或者變量單獨(dú)去使用。

let  httpError = (401,"未授權(quán)")//!< httpError可以被描述為(Int,String)類(lèi)型的元組
let (code,error) = httpError
print(code,error)//code:401   error 未授權(quán)

元組中包含許多項(xiàng)不同類(lèi)型的常量或者變量,我們需要有針對(duì)性的分解出某一個(gè)元素。

let someGrop =  ("元組",401,"未授權(quán)",[1,3],true,["name" : "張三"])
let (name,_,_,_,_,_) = someGrop
print(name)

使用從零開(kāi)始的索引訪問(wèn)元組中的各個(gè)元素值

let someGrop =  ("元組",401,"未授權(quán)",[1,3],true,["name" : "張三"])
let name = someGrop.0
let num =  someGrop.1
let des = someGrop.2
let array = someGrop.3
print(name,num,des,array)

定義元組時(shí)可以命名元組中各個(gè)元素。

let httpError = (code:401,error:"未授權(quán)")
//元素單獨(dú)使用
print(httpError.code,httpError.error)

定義元組時(shí)不賦初值

let httpSubError : (Int,String)?
httpSubError = (401,"未授權(quán)")
print(httpSubError!)
//也可以
let httpSubError : (code:Int,error:String)?
httpSubError = (401,"未授權(quán)")
print(httpSubError!.code)

可選項(xiàng)(Optionals):當(dāng)某個(gè)類(lèi)型變量的值可能為空的場(chǎng)景,我們需要使用Optionals(可選項(xiàng))。一個(gè)可選代表兩種可能:有值并且你可以解開(kāi)可選項(xiàng)(optional)的包獲取到這個(gè)值,否則沒(méi)有值。

選項(xiàng)的概念在C或Objective-C中不存在。Objective-C中最接近的是一個(gè)具備返回值的方法在缺少有效對(duì)象的情況下可以返回nil,否則返回此對(duì)象。但是這種場(chǎng)景只適用于對(duì)象 ,而對(duì)于結(jié)構(gòu)體,基本C類(lèi)型或枚舉值這些類(lèi)型,Objective-C的方法是返回特殊值(例如NSNotFound)來(lái)表示這些類(lèi)型不存在的情況。Swift的選項(xiàng)可以讓我們表示任何類(lèi)型都沒(méi)有值的情況,而不需要特殊的常量。

對(duì)于非可選類(lèi)型的常量或變量我們不能使用nil,如果我們的代碼需要在變量或常量缺少值的情況下正常運(yùn)行,那么我們就應(yīng)該始終聲明變量或變量為相應(yīng)類(lèi)型的可選值
在不提供默認(rèn)值的情況下定義可選變量var str: String?系統(tǒng)將會(huì)自動(dòng)為變量設(shè)置nil,Swift中的nil與Objective-C不同。在Objective-C中,nil是一個(gè)指向不存在的對(duì)象的指針。在Swift中,nil不是指針,而是一個(gè)確定的類(lèi)型的變量或常量的一個(gè)缺省值。任何類(lèi)型的可選值都能設(shè)置nil,不僅僅只是對(duì)象類(lèi)型
if語(yǔ)句和強(qiáng)制解包: 使用if語(yǔ)句通過(guò)“等于”運(yùn)算符(==)或“不等于”運(yùn)算符(!=)比較可選項(xiàng),來(lái)確定可選項(xiàng)是否包含值nil

let possibleNumber = "123"
let convertedNumber : Int? = Int(possibleNumber)
if convertedNumber != nil {
//! 當(dāng)我們確定了convertedNumber的值不可能為nil便可以使用!進(jìn)行強(qiáng)制解包獲取可選包中的值
print(convertedNumber!)

強(qiáng)制解包可選的值:一旦確定可選項(xiàng)確實(shí)包含值,就可以通過(guò)在可選項(xiàng)名稱的末尾添加感嘆號(hào)!來(lái)訪問(wèn)其基礎(chǔ)值。

可選綁定:使用可選綁定來(lái)確定可選項(xiàng)是否包含值,如果包含值,則這個(gè)值可用于臨時(shí)常量或變量的值。可選綁定可與if和while語(yǔ)句一起使用,以檢查可選內(nèi)部的值,并將該值提取為常量或變量,作為單個(gè)操作的一部分。
可選綁定,if語(yǔ)句示例

let possibleNumber = "1234"
let convertedNumber : Int? = Int(possibleNumber)
if let tempValue = convertedNumber {
    print(tempValue);
} else {
    print("沒(méi)有值")
}
if var tempVar = convertedNumber {
     tempVar = tempVar + 1
     print(tempVar);
} else {
     print("沒(méi)有值")
}

代碼解讀:如果Int類(lèi)型的可選項(xiàng)convertedNumber ,通過(guò)Int(possibleNumber)返回了一個(gè)值,則使用此值設(shè)置一個(gè)新的常量tempValue。條件成立時(shí),tempValue是被一個(gè)沒(méi)有可選包的確定的值初始化的,因此沒(méi)有必要使用!后綴來(lái)訪問(wèn)它的值。
單個(gè)if語(yǔ)句中可以包含盡可能多的可選綁定布爾條件,并以逗號(hào)分隔。如果可選綁定中的任何值是nil,或任何布爾條件求值為false,則整個(gè)語(yǔ)句的條件是false。示例:

if let firstNumber = Int("4"), let secondNumber = Int("42"), firstNumber < secondNumber && secondNumber < 100 {
    print("\(firstNumber) < \(secondNumber) < 100")
} else {
    print("不成立")
}
//等效的表達(dá)形式
if let firstNumber = Int("4") {
    if let secondNumber = Int("42") {
        if firstNumber < secondNumber && secondNumber < 100 {
            print("\(firstNumber) < \(secondNumber) < 100")
        }
    }
}

隱式解包(未包裝)的可選項(xiàng)
可選項(xiàng):允許我們的常量或變量不存在,使用時(shí),可以使用if 語(yǔ)句檢查是否nil或者使用可選綁定進(jìn)行解包,以保證可選項(xiàng)在有值得情況下正確的訪問(wèn)值。
隱式解包(未包裝)的可選項(xiàng):我們從程序的結(jié)構(gòu)可以得出,在我們首次設(shè)置可選項(xiàng)的值以后,這個(gè)可選項(xiàng)將總是會(huì)有值,每次調(diào)用都不可能是nil。基于此我們可能會(huì)想,那么我們就沒(méi)必要每次訪問(wèn)值時(shí),都檢查和解包可選的值。那么上述場(chǎng)景中可選項(xiàng),便可以被定義為隱式解包(未包裝)的可選項(xiàng)。
可選類(lèi)型的定義是類(lèi)型后加?:(String?),而隱式解包的可選項(xiàng)是在類(lèi)型后加!:(String!)
隱式解包的可選項(xiàng)幕后其實(shí)是一個(gè)正常的可選項(xiàng),但是我們可以像非可選值那樣去使用,而不用每次訪問(wèn)都要先對(duì)可選項(xiàng)的值解包。
當(dāng)使用一個(gè)字符串類(lèi)型的可選項(xiàng)和一個(gè)隱式解包的字符串類(lèi)型的可選項(xiàng)去訪問(wèn)它們字符串類(lèi)型可選包(wrapped)中的確定值會(huì)有差異。
1.定義了字符串類(lèi)型的可選項(xiàng),并賦初值。在使用時(shí)需要針對(duì)可選的字符串,進(jìn)行強(qiáng)制解包,以獲取其中的確定值。需要加

 //! 1.定義了字符串類(lèi)型的可選項(xiàng),并賦初值。
let possibleString: String? = "An optional string."
let forcedString: String = possibleString! // 使用時(shí)需要針對(duì)可選的字符串,進(jìn)行強(qiáng)制解包,以獲取其中的確定值。

2.定義了隱式解包的字符串類(lèi)型的可選項(xiàng),并賦初始值。使用時(shí),不在需要針對(duì)隱式解包的字符串類(lèi)型的可選項(xiàng),進(jìn)行解包。不再需要!

 //! 2.定義了隱式解包的字符串類(lèi)型的可選項(xiàng),并賦初始值。
let assumedString: String! = "An implicitly unwrapped optional string."
let implicitString: String = assumedString // 使用時(shí),不在需要針對(duì)隱式解包的字符串類(lèi)型的可選項(xiàng),進(jìn)行解包 即:不再需要!

3.如果隱式解包的可選項(xiàng)是nil并且嘗試訪問(wèn)其包裝值,則會(huì)觸發(fā)運(yùn)行時(shí)錯(cuò)誤。結(jié)果與在不包含值的普通可選項(xiàng)之后放置感嘆號(hào)完全相同。同時(shí)也可以將隱式解包的可選項(xiàng)視為普通可選項(xiàng),以檢查它是否包含值:if可選綁定

let assumedString: String! = nil
let implicitString: String = assumedString
print(implicitString)//!< 崩潰:隱式解包一個(gè)可選項(xiàng)的值時(shí)發(fā)現(xiàn)了nil。Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value

錯(cuò)誤處理: 響應(yīng)程序在執(zhí)行期間可能遇到的錯(cuò)誤情況。
定義可以拋出錯(cuò)誤的函數(shù)

func canThrowAnError() throws {
    // this function may or may not throw an error
}

函數(shù)聲明時(shí)在參數(shù)與返回值之間使用關(guān)鍵字throws,代表這個(gè)函數(shù)可能拋出錯(cuò)誤。在調(diào)用這個(gè)可能拋出錯(cuò)誤函數(shù)時(shí)需要在表達(dá)式前放置try關(guān)鍵字。
當(dāng)使用catch分句處理錯(cuò)誤時(shí),Swift會(huì)自動(dòng)把函數(shù)拋出的錯(cuò)誤,自動(dòng)傳播出當(dāng)前的函數(shù)作用域。

do {
    try canThrowAnError()
    // no error was thrown
} catch {
    // an error was thrown
}

以下是如何使用錯(cuò)誤處理來(lái)響應(yīng)不同錯(cuò)誤條件的示例:
1.定義錯(cuò)誤
Error類(lèi)型:表示一個(gè)能夠被拋出(thrown)的錯(cuò)誤。聲明的任何類(lèi)型只要遵守了 Error的協(xié)議都能夠在Swift的錯(cuò)誤處理系統(tǒng)中表示一個(gè)錯(cuò)誤。因?yàn)?code>Error協(xié)議沒(méi)有要求自身必須實(shí)現(xiàn),我們可以在創(chuàng)建的任何自定義類(lèi)型中聲明遵守這個(gè)協(xié)議即可。

public protocol Error {
}
extension Error {
}
extension Error where Self : RawRepresentable, Self.RawValue : FixedWidthInteger {
}

Error枚舉:Swift的枚舉很適合表示簡(jiǎn)單的錯(cuò)誤。我們可以創(chuàng)建一個(gè)遵守Error 協(xié)議的枚舉類(lèi)型,并在枚舉中定義每一種可能的錯(cuò)誤事例。

enum HttpError: Error {
    case authError
    case netWorkError
    case serviceError
}

2.定義方法

func requestWebData(status: String) throws -> Void {
    
    let status = status
    if status == "401" {
        throw HttpError.authError
    } else if status == "500" {
        throw HttpError.serviceError
    } else if status == "404"{
        throw HttpError.netWorkError
    } else {
        print("一切正常");
    }
    
}
func noThrowErrorCanDoSomeThing () {
    print("沒(méi)有錯(cuò)誤拋出,可以做我們要做的事情")
}

func handleServiceError() {
    print("服務(wù)器錯(cuò)誤,需要重新連接")
}
func handleAuthError () throws {
    print("授權(quán)失敗了,選擇重新登錄")
    //! 網(wǎng)絡(luò)請(qǐng)求
    do {
        try requestWebData(status: "404")
    } catch let error as HttpError  {
        throw error
    }
}
func handleNetWorkError(){
    print("網(wǎng)絡(luò)錯(cuò)誤了,檢查網(wǎng)絡(luò)")
}

3.使用do try catch方法調(diào)用并處理異常。

do {
    try requestWebData(status:"400")
    //沒(méi)有出現(xiàn)錯(cuò)誤,做事情
    noThrowErrorCanDoSomeThing()
} catch HttpError.authError {
    
    do {
        try handleAuthError()
    } catch HttpError.netWorkError {
        print("授權(quán)登錄時(shí)出現(xiàn)網(wǎng)絡(luò)錯(cuò)誤")
    } catch {
        print("授權(quán)登錄時(shí)出現(xiàn)其他錯(cuò)誤")
    }
    
} catch HttpError.netWorkError {
    handleNetWorkError()
} catch HttpError.serviceError {
    handleServiceError()
} catch {
    print("其他錯(cuò)誤")//!< 這個(gè)catch就是在補(bǔ)全錯(cuò)誤的處理,否則編譯器指示錯(cuò)誤
}

斷言和前置條件:斷言和前置條件是在運(yùn)行時(shí)發(fā)生的檢查。在執(zhí)行任何進(jìn)一步的代碼之前,使用它們來(lái)確保代碼滿足基本條件。如果斷言或前置條件中的布爾條件求值為true,則代碼執(zhí)行將照常繼續(xù)。如果條件評(píng)估為false,則程序的當(dāng)前狀態(tài)無(wú)效,代碼執(zhí)行結(jié)束,程序終止。
斷言:只有debug環(huán)境下才可以生效。
1.代碼未進(jìn)行條件檢查

let num = -1        
assert(num > 0, "num不能為負(fù)數(shù)")

2.代碼進(jìn)行了條件檢查

let num = -1
if num > 10 {
} else if num >= 0 {
} else {
    assertionFailure("num不能為負(fù)數(shù)")//!< 陳述條件的信息
}

前置條件:在release環(huán)境下也可以生效。

let num = -1
precondition(num > 0, "num不能為負(fù)數(shù)")

注意:

  • 如果代碼中存儲(chǔ)不會(huì)更改的值,需要始終使用let關(guān)鍵字將其聲明為常量。存儲(chǔ)需要更改的值需要始終使用var關(guān)鍵字將其聲明為變量。
  • 如果我們?yōu)槎x的常量或變量提供了初始值,則不需要編寫(xiě)類(lèi)型注釋?zhuān)琒wift可以進(jìn)行類(lèi)型推斷得出該常量或變量的類(lèi)型 。若只是聲明并未賦初值,如var str1 : String則需要提供類(lèi)型注釋
  • 常量或變量命名使用與Swift關(guān)鍵字相同的名稱時(shí),需要使用``包裹該關(guān)鍵字名稱。盡量避免使用關(guān)鍵字作為名稱。
  • 除非我們需要與平臺(tái)機(jī)器的位數(shù)一致的無(wú)符號(hào)整型時(shí)使用UInt。其他情況Int則優(yōu)選,即使已知要存儲(chǔ)的值是非負(fù)的。Int對(duì)整數(shù)值的一致使用有助于代碼互操作性,避免在不同數(shù)字類(lèi)型之間進(jìn)行轉(zhuǎn)換,有利于整數(shù)類(lèi)型推斷。
  • Double至少可以精確到小數(shù)點(diǎn)后15位,Float的精度可以少至6位小數(shù)。任何一種類(lèi)型適當(dāng)?shù)那闆r下,Double是首選。代碼中也可以根據(jù)使用的值的性質(zhì)和范圍選擇適當(dāng)浮點(diǎn)類(lèi)型。
  • 元組對(duì)于簡(jiǎn)單的不同類(lèi)型值的組合很有用。它們不適合創(chuàng)建復(fù)雜的數(shù)據(jù)結(jié)構(gòu)。如果我們的數(shù)據(jù)結(jié)構(gòu)可能更復(fù)雜,應(yīng)當(dāng)使用構(gòu)建為類(lèi)或結(jié)構(gòu),而不是元組。
  • 嘗試使用!訪問(wèn)不存在的可選值會(huì)觸發(fā)運(yùn)行時(shí)錯(cuò)誤。在使用!強(qiáng)制解包可選變量或常量的值之前,請(qǐng)務(wù)必確保可選項(xiàng)包含的值非nil
  • 在if語(yǔ)句中使用可選綁定創(chuàng)建的常量和變量?jī)H在if語(yǔ)句的主體中可用。相反,使用guard語(yǔ)句創(chuàng)建的常量和變量在主體語(yǔ)句后面的代碼行中仍然可用。
let possibleNumber = "1234"
let convertedNumber : Int? = Int(possibleNumber)
guard let tempValue = convertedNumber else {
   print("沒(méi)有值")
   //只是跳出方法體
   return
}
print("guard\(tempValue)")
  • 當(dāng)變量在后面使用時(shí)可能變?yōu)閚il,不要使用隱式解包的可選項(xiàng)。如果需要在變量的生命周期內(nèi)檢查值是否為nil,請(qǐng)始終使用普通的可選類(lèi)型。
var assumedString: String! = "俺是張飛"
assumedString = nil;
let implicitString: String = assumedString //< 崩潰:隱式解包一個(gè)可選項(xiàng)的值時(shí)發(fā)現(xiàn)了nil。Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value
  • 使用throws關(guān)鍵字表明這個(gè)方法會(huì)拋出異常,所以需要try catch 語(yǔ)句進(jìn)行錯(cuò)誤處理,否則方法直接調(diào)用不會(huì)被允許,會(huì)報(bào)錯(cuò)。同時(shí)對(duì)于錯(cuò)誤的處理(catch)必須是全面的(窮盡所有可能出現(xiàn)的錯(cuò)誤),否則此處的錯(cuò)誤不會(huì)被執(zhí)行,編譯器會(huì)指示錯(cuò)誤。

參考資料:
swift 5.1官方編程指南


推薦文章:
iOS UI狀態(tài)保存和恢復(fù)(三)
iOS UI狀態(tài)保存和恢復(fù)(二)
iOS UI狀態(tài)保存和恢復(fù)(一)
iOS 中精確定時(shí)的常用方法
Sign In With Apple(一)
算法小專(zhuān)欄:動(dòng)態(tài)規(guī)劃(一)
Dart基礎(chǔ)(一)
Dart基礎(chǔ)(二)
Dart基礎(chǔ)(三)
Dart基礎(chǔ)(四)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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