Swift基礎(chǔ)_1

Swift 是一門(mén)開(kāi)發(fā) iOS, macOS, watchOS 和 tvOS 應(yīng)用的新語(yǔ)言。然而,如果你有 C 或者 Objective-C 開(kāi)發(fā)經(jīng)驗(yàn)的話(huà),你會(huì)發(fā)現(xiàn) Swift 的很多內(nèi)容都是你熟悉的。
swift swift2
Swift 包含了 C 和 Objective-C 上所有基礎(chǔ)數(shù)據(jù)類(lèi)型,Int 表示整型值;DoubleFloat表示浮點(diǎn)型值;Bool是布爾型值;String是文本型數(shù)據(jù)。 Swift 還提供了三個(gè)基本的集合類(lèi)型,ArraySetDictionary

就像 C 語(yǔ)言一樣,Swift 使用變量來(lái)進(jìn)行存儲(chǔ)并通過(guò)變量名來(lái)關(guān)聯(lián)值。在 Swift 中,廣泛的使用著值不可變的變量,它們就是常量,而且比 C 語(yǔ)言的常量更強(qiáng)大。在 Swift 中,如果你要處理的值不需要改變,那使用常量可以讓你的代碼更加安全并且更清晰地表達(dá)你的意圖。

除了我們熟悉的類(lèi)型,Swift 還增加了 Objective-C 中沒(méi)有的高階數(shù)據(jù)類(lèi)型比如元組(Tuple)。元組可以讓你創(chuàng)建或者傳遞一組數(shù)據(jù),比如作為函數(shù)的返回值時(shí),你可以用一個(gè)元組可以返回多個(gè)值

Swift 還增加了可選(Optional)類(lèi)型,用于處理值缺失的情況。可選表示 “那兒有一個(gè)值,并且它等于 x ” 或者 “那兒沒(méi)有值” 。可選有點(diǎn)像在 Objective-C 中使用 nil ,但是它可以用在任何類(lèi)型上,不僅僅是類(lèi)。可選類(lèi)型比 Objective-C 中的 nil 指針更加安全也更具表現(xiàn)力,它是 Swift 許多強(qiáng)大特性的重要組成部分。

Swift 是一門(mén)類(lèi)型安全的語(yǔ)言,這意味著 Swift 可以讓你清楚地知道值的類(lèi)型。如果你的代碼需要一個(gè) String ,類(lèi)型安全會(huì)阻止你不小心傳入一個(gè) Int 。同樣的,如果你的代碼需要一個(gè) String,類(lèi)型安全會(huì)阻止你意外傳入一個(gè)可選的 String 。類(lèi)型安全可以幫助你在開(kāi)發(fā)階段盡早發(fā)現(xiàn)并修正錯(cuò)誤

常量和變量

常量和變量把一個(gè)名字和制定類(lèi)型的指聯(lián)系起來(lái),比如把"name" 和 "Edison"聯(lián)系起來(lái)

聲明常量和變量

let聲明常量,var聲明變量

var helleStr : NSString = "hello"
var i = 0, b=9, c = "nihao"

注意:如果你的代碼中有不需要改變的值,
請(qǐng)用let把它聲明成常量

類(lèi)型標(biāo)注

當(dāng)你聲明常量或者變量的可以添加直接直接添加類(lèi)型
比如

var nameStr : NSString 
var helleStr : NSString = "hello"

這樣就給常量或者變量聲明的屬性,表示這個(gè)變量?jī)?chǔ)存的是制定類(lèi)型的值

一般來(lái)說(shuō)我們很少需要寫(xiě)類(lèi)型標(biāo)注,如果你聲明常量或者變量的時(shí)候初始化一個(gè)值,swift可以推斷出這個(gè)常量或者變量的類(lèi)型

常量和變量的命名

swift允許你有你任何你喜歡的字符座位常量和變量名,包括unicode編碼

let ??二 = "dog"
let 天涯 = "tianya"

常量與變量名不能包含數(shù)學(xué)符號(hào),箭頭,保留的(或者非法的)Unicode 碼位,連線(xiàn)與制表符。也不能以數(shù)字開(kāi)頭,但是可以在常量與變量名的其他地方包含數(shù)字

一旦你將常量或者變量聲明為確定的類(lèi)型,你就不能使用相同的名字再次進(jìn)行聲明,或者改變其存儲(chǔ)的值的類(lèi)型。同時(shí),你也不能將常量與變量進(jìn)行互轉(zhuǎn)

輸出常量和變量

print(helleStr)
print("hellstr:\(helleStr)  tianya:\(天涯)")

分號(hào)

與大部分編程不同,swift并不強(qiáng)制要求在每句代碼后都得加上分號(hào),但是有一種情況下,是必須要加的,就是在同一行寫(xiě)多句獨(dú)立的代碼

var intA = 3 ; print(intA)

整數(shù)

整數(shù)就是沒(méi)有小數(shù)部分的數(shù)字,比如 42 和 -23 。整數(shù)可以是 有符號(hào)(正、負(fù)、零)或者 無(wú)符號(hào)(正、零)。

Swift 提供了8,16,32和64位的有符號(hào)和無(wú)符號(hào)整數(shù)類(lèi)型。這些整數(shù)類(lèi)型和 C 語(yǔ)言的命名方式很像,比如8位無(wú)符號(hào)整數(shù)類(lèi)型是UInt8,32位有符號(hào)整數(shù)類(lèi)型是 Int32 。就像 Swift 的其他類(lèi)型一樣,整數(shù)類(lèi)型采用大寫(xiě)命名法

Int

一般來(lái)說(shuō),你不需要專(zhuān)門(mén)指定證書(shū)的長(zhǎng)度,swift提供了一個(gè)特殊的整數(shù)類(lèi)型Int,長(zhǎng)度與當(dāng)前平臺(tái)的原生長(zhǎng)度一樣

  • 在32位平臺(tái)上,IntInt32 長(zhǎng)度一樣
  • 在64位平臺(tái)上,IntInt64 長(zhǎng)度一樣
    除非你需要特定長(zhǎng)度的整數(shù),一般來(lái)說(shuō)使用 Int 就夠了。這可以提高代碼一致性和可復(fù)用性。即使是在32位平臺(tái)上,Int 可以存儲(chǔ)的整數(shù)范圍也可以達(dá)到 -2,147,483,648 ~ 2,147,483,647 ,大多數(shù)時(shí)候這已經(jīng)足夠大了

UInt

Swift 也提供了一個(gè)特殊的無(wú)符號(hào)類(lèi)型 UInt,長(zhǎng)度與當(dāng)前平臺(tái)的原生字長(zhǎng)相同

浮點(diǎn)數(shù)

浮點(diǎn)數(shù)是有小數(shù)部分的數(shù)字,比如3.14159,0.2,-7.456
浮點(diǎn)數(shù)比整數(shù)表示的范圍更大,可以?xún)?chǔ)存比Int更大或者更小的數(shù)字,swift也提供了兩種浮點(diǎn)數(shù)

  • Double
    表示64位浮點(diǎn)數(shù),當(dāng)你需要存儲(chǔ)很大或者很高精度的浮點(diǎn)數(shù)時(shí)請(qǐng)使用此類(lèi)型
  • Float
    表示32位浮點(diǎn)數(shù)。精度要求不高的話(huà)可以使用此類(lèi)型

Double精確度很高,至少有15位數(shù)字,而Float只有6位數(shù)字。選擇哪個(gè)類(lèi)型取決于你的代碼需要處理的值的范圍,在兩種類(lèi)型都匹配的情況下,將優(yōu)先選擇 Double

類(lèi)型安全和類(lèi)型推斷

Swift 是一個(gè)類(lèi)型安全(type safe)的語(yǔ)言。類(lèi)型安全的語(yǔ)言可以讓你清楚地知道代碼要處理的值的類(lèi)型。如果你的代碼需要一個(gè)String,你絕對(duì)不可能不小心傳進(jìn)去一個(gè)Int

由于 Swift 是類(lèi)型安全的,所以它會(huì)在編譯你的代碼時(shí)進(jìn)行類(lèi)型檢查(type checks),并把不匹配的類(lèi)型標(biāo)記為錯(cuò)誤。這可以讓你在開(kāi)發(fā)的時(shí)候盡早發(fā)現(xiàn)并修復(fù)錯(cuò)誤

當(dāng)你要處理不同類(lèi)型的值時(shí),類(lèi)型檢查可以幫你避免錯(cuò)誤。然而,這并不是說(shuō)你每次聲明常量和變量的時(shí)候都需要顯式指定類(lèi)型。如果你沒(méi)有顯式指定類(lèi)型,Swift 會(huì)使用類(lèi)型推斷(type inference)來(lái)選擇合適的類(lèi)型。有了類(lèi)型推斷,編譯器可以在編譯代碼的時(shí)候自動(dòng)推斷出表達(dá)式的類(lèi)型。原理很簡(jiǎn)單,只要檢查你賦的值即可

因?yàn)橛蓄?lèi)型推斷,和 C 或者 Objective-C 比起來(lái) Swift 很少需要聲明類(lèi)型。常量和變量雖然需要明確類(lèi)型,但是大部分工作并不需要你自己來(lái)完成

當(dāng)你聲明常量或者變量并賦初值的時(shí)候類(lèi)型推斷非常有用。當(dāng)你在聲明常量或者變量的時(shí)候賦給它們一個(gè)字面量(literal value 或 literal)即可觸發(fā)類(lèi)型推斷。(字面量就是會(huì)直接出現(xiàn)在你代碼中的值,比如 42 和 3.14159 。)

例如,如果你給一個(gè)新常量賦值 10 并且沒(méi)有標(biāo)明類(lèi)型,Swift 可以推斷出常量類(lèi)型是 Int ,因?yàn)槟憬o它賦的初始值看起來(lái)像一個(gè)整數(shù)

let intValue = 10

同理,如果你沒(méi)有給浮點(diǎn)字面量標(biāo)明類(lèi)型,Swift 會(huì)推斷你想要的是 Double

let douValue = 4.675

當(dāng)推斷浮點(diǎn)數(shù)的類(lèi)型時(shí),Swift 總是會(huì)選擇 Double 而不是Float

如果表達(dá)式中同時(shí)出現(xiàn)了整數(shù)和浮點(diǎn)數(shù),會(huì)被推斷為 Double 類(lèi)型:

let value = 10+7.78

數(shù)值型字面量

整數(shù)字面量可以被寫(xiě)作

  • 一個(gè)十進(jìn)制數(shù),沒(méi)有前綴
  • 一個(gè)二進(jìn)制數(shù),前綴是 0b
  • 一個(gè)八進(jìn)制數(shù),前綴是0o
  • 一個(gè)十六進(jìn)制數(shù),前綴是0x

浮點(diǎn)字面量可以是十進(jìn)制(沒(méi)有前綴)或者是十六進(jìn)制(前綴是 0x ),小數(shù)點(diǎn)兩邊必須有至少一個(gè)十進(jìn)制數(shù)字(或者是十六進(jìn)制的數(shù)字)。十進(jìn)制浮點(diǎn)數(shù)也可以有一個(gè)可選的指數(shù)(exponent),通過(guò)大寫(xiě)或者小寫(xiě)的 e 來(lái)指定;十六進(jìn)制浮點(diǎn)數(shù)必須有一個(gè)指數(shù),通過(guò)大寫(xiě)或者小寫(xiě)的 p 來(lái)指定

如果一個(gè)十進(jìn)制數(shù)的指數(shù)為 exp,那這個(gè)數(shù)相當(dāng)于基數(shù)和10^exp的乘積

  • 1.25e2 表示 1.25 × 10^2,等于 125.0
    -1.25e-2 表示 1.25 × 10^-2,等于0.0125

如果一個(gè)十六進(jìn)制數(shù)的指數(shù)為exp,那這個(gè)數(shù)相當(dāng)于基數(shù)和2^exp的乘積

  • 0xFp2 表示 15 × 2^2,等于 60.0
  • 0xFp-2 表示 15 × 2^-2,等于 3.75

數(shù)值型類(lèi)型轉(zhuǎn)換

通常來(lái)講,即使代碼中的整數(shù)常量和變量已知非負(fù),也請(qǐng)使用Int類(lèi)型。總是使用默認(rèn)的整數(shù)類(lèi)型可以保證你的整數(shù)常量和變量可以直接被復(fù)用并且可以匹配整數(shù)類(lèi)字面量的類(lèi)型推斷

只有在必要的時(shí)候才使用其他整數(shù)類(lèi)型,比如要處理外部的長(zhǎng)度明確的數(shù)據(jù)或者為了優(yōu)化性能、內(nèi)存占用等等。使用顯式指定長(zhǎng)度的類(lèi)型可以及時(shí)發(fā)現(xiàn)值溢出并且可以暗示正在處理特殊數(shù)據(jù)

整數(shù)轉(zhuǎn)換

不同整數(shù)類(lèi)型的變量和常量可以存儲(chǔ)不同范圍的數(shù)字。Int8類(lèi)型的常量或者變量可以存儲(chǔ)的數(shù)字范圍是-128~127,而UInt8類(lèi)型的常量或者變量能存儲(chǔ)的數(shù)字范圍是0~255。如果數(shù)字超出了常量或者變量可存儲(chǔ)的范圍,編譯的時(shí)候會(huì)報(bào)錯(cuò)

F6724E21-2AF9-49CB-876E-ECFF0350E86B.png

由于每種整數(shù)類(lèi)型都可以存儲(chǔ)不同范圍的值,所以你必須根據(jù)不同情況選擇性使用數(shù)值型類(lèi)型轉(zhuǎn)換。這種選擇性使用的方式,可以預(yù)防隱式轉(zhuǎn)換的錯(cuò)誤并讓你的代碼中的類(lèi)型轉(zhuǎn)換意圖變得清晰

要將一種數(shù)字類(lèi)型轉(zhuǎn)換成另一種,你要用當(dāng)前值來(lái)初始化一個(gè)期望類(lèi)型的新數(shù)字,這個(gè)數(shù)字的類(lèi)型就是你的目標(biāo)類(lèi)型。在下面的例子中,常量twoThousand是UInt16類(lèi)型,然而常量one是UInt8類(lèi)型。它們不能直接相加,因?yàn)樗鼈冾?lèi)型不同。所以要調(diào)用UInt16(one)來(lái)創(chuàng)建一個(gè)新的UInt16數(shù)字并用one的值來(lái)初始化,然后使用這個(gè)新數(shù)字來(lái)計(jì)算

let twoThousand: UInt16 = 2_000
let one: UInt8 = 1
let twoThousandAndOne = twoThousand + UInt16(one)

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

整數(shù)和浮點(diǎn)數(shù)的轉(zhuǎn)換必須顯式指定類(lèi)型:

let intC   = 33
let floatB = 4.67
let doubleC = Double(intC) + floatB

類(lèi)型別名

類(lèi)型別名(type aliases)就是給現(xiàn)有類(lèi)型定義另一個(gè)名字。你可以使用typealias關(guān)鍵字來(lái)定義類(lèi)型別名

當(dāng)你想要給現(xiàn)有類(lèi)型起一個(gè)更有意義的名字時(shí),類(lèi)型別名非常有用。假設(shè)你正在處理特定長(zhǎng)度的外部資源的數(shù)據(jù):

typealias AudioSample = UInt16

定義了一個(gè)類(lèi)型別名之后,你可以在任何使用原始名的地方使用別名:

var maxAmplitudeFound = AudioSample.min
// maxAmplitudeFound 現(xiàn)在是 0

本例中,AudioSample被定義為UInt16的一個(gè)別名。因?yàn)樗莿e名,AudioSample.min實(shí)際上是UInt16.min,所以會(huì)給maxAmplitudeFound賦一個(gè)初值0。

布爾值

Swift 有一個(gè)基本的布爾(Boolean)類(lèi)型,叫做Bool。布爾值指邏輯上的值,因?yàn)樗鼈冎荒苁钦婊蛘呒佟wift 有兩個(gè)布爾常量,truefalse

let boolA = true
let boolB = false

boolA 和 boolB 的類(lèi)型會(huì)被推斷為 Bool,因?yàn)樗鼈兊某踔凳遣紶栕置媪俊>拖裰疤岬降?Int 和 Double 一樣,如果你創(chuàng)建變量的時(shí)候給它們賦值 true 或者 false,那你不需要將常量或者變量聲明為 Bool 類(lèi)型。初始化常量或者變量的時(shí)候如果所賦的值類(lèi)型已知,就可以觸發(fā)類(lèi)型推斷,這讓 Swift 代碼更加簡(jiǎn)潔并且可讀性更高

當(dāng)你編寫(xiě)條件語(yǔ)句比如if語(yǔ)句,布爾值就很有作用

if boolA {
    
    print("YES")
}else{
    print("NO")
}

元組

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

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

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

let (name,age,height) = ("Edison",13,177)
print(name,age,height)

還可以只通過(guò)下標(biāo)來(lái)訪(fǎng)問(wèn)元組的單個(gè)元素

let faceId = ("good",144)
let (face,weight) = faceId
print("\(faceId.0) --  \(faceId.1)")

你可以在定義元組的時(shí)候給單個(gè)元素命名

let tupleName = (eName:"edison",eAge:14)
print("enmae=\(tupleName.eName)  age=\(tupleName.eAge)")

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

可選類(lèi)型

使用可選類(lèi)型(optionals)來(lái)處理可能確實(shí)的情況,可選類(lèi)型表示:

  • 有值,等于x
  • 沒(méi)有值

注意
c和oc中并沒(méi)有可選類(lèi)型這個(gè)概念,最接近這個(gè)概念,是oc中的一個(gè)特性(一個(gè)方法要么返回對(duì)象,要么返回nil,nil表示確實(shí)一個(gè)合法對(duì)象,但這只對(duì)oc對(duì)象有作用,對(duì)c,結(jié)構(gòu)體都不能用,對(duì)于這些類(lèi)型,Objective-C 方法一般會(huì)返回一個(gè)特殊值(比如NSNotFound)來(lái)暗示值缺失。這種方法假設(shè)方法的調(diào)用者知道并記得對(duì)特殊值進(jìn)行判斷),然而,Swift 的可選類(lèi)型可以讓你暗示任意類(lèi)型的值缺失,并不需要一個(gè)特殊值

let的可選項(xiàng)沒(méi)有初始化,var的可選項(xiàng)初始值為nil

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

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

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

因?yàn)樵摌?gòu)造器可能會(huì)失敗,所以它返回一個(gè)可選類(lèi)型(optional)Int,而不是一個(gè) Int。一個(gè)可選的 Int 被寫(xiě)作 Int? 而不是 Int。問(wèn)號(hào)暗示包含的值是可選類(lèi)型,也就是說(shuō)可能包含 Int 值也可能不包含值。(不能包含其他任何值比如 Bool 值或者 String 值。只能是 Int 或者什么都沒(méi)有。)

nil

你可以給可選變量賦值為nil來(lái)表示它沒(méi)有值:

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

注意
nil不能用于非可選的常量和變量。如果你的代碼中有常量或者變量需要處理值缺失的情況,請(qǐng)把它們聲明成對(duì)應(yīng)的可選類(lèi)型
如果你聲明一個(gè)可選常量或者變量但是沒(méi)有賦值,它們會(huì)自動(dòng)被設(shè)置為 nil

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

if語(yǔ)句以及強(qiáng)制解析

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

如果可選類(lèi)型有值,它將不等于 nil

var oStr = "oStr"
var a = Int(oStr)

if a != nil {
    print("a有值")
}else{
    print("a無(wú)值")
}
//結(jié)果是a無(wú)值

當(dāng)你確定可選類(lèi)型確實(shí)包含值之后,你可以在可選的名字后面加一個(gè)感嘆號(hào)(!)來(lái)獲取值。這個(gè)驚嘆號(hào)表示“我知道這個(gè)可選有值,請(qǐng)使用它

var oStr = "123"
var a = Int(oStr)

if a != nil {
    print("a有值\(a!)")
}else{
    print("a無(wú)值")
}

但是如果用! 來(lái)強(qiáng)制解析不存在對(duì)可選值,就會(huì)出錯(cuò)

var oStr = "oStr"
var a = Int(oStr)
print("a有值\(a!)")
// unexpectedly found nil while unwrapping an Optional value   
這個(gè)奔潰就是強(qiáng)行解包一個(gè)nil值的變量

注意:
使用 ! 來(lái)獲取一個(gè)不存在的可選值會(huì)導(dǎo)致運(yùn)行時(shí)錯(cuò)誤。使用! 來(lái)強(qiáng)制解析值之前,一定要確定可選包含一個(gè)非 nil 的值

可選綁定

使用可選綁定(optional binding)來(lái)判斷可選類(lèi)型是否包含值,如果包含就把值賦給一個(gè)臨時(shí)常量或者變量

可選綁定可以用在 ifwhile 語(yǔ)句中,這條語(yǔ)句不僅可以用來(lái)判斷可選類(lèi)型中是否有值,同時(shí)可以將可選類(lèi)型中的值賦給一個(gè)常量或者變量

像下面這樣在 if 語(yǔ)句中寫(xiě)一個(gè)可選綁定:

if let constantName = someOptional {
    statements
}

你可以像上面這樣使用可選綁定來(lái)重寫(xiě) possibleNumber 這個(gè)

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

這段代碼可以被理解為:
“如果 Int(possibleNumber) 返回的可選Int 包含一個(gè)值,創(chuàng)建一個(gè)叫做 actualNumber 的新常量并將可選包含的值賦給它。”

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

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

你可以包含多個(gè)可選綁定或多個(gè)布爾條件在一個(gè)if語(yǔ)句中,只要使用逗號(hào)分開(kāi)就行。只要有任意一個(gè)可選綁定的值為nil,或者任意一個(gè)布爾條件為false,則整個(gè)if條件判斷為false,這時(shí)你就需要使用嵌套if 條件語(yǔ)句來(lái)處理,如下所示:

if let firstNumber = Int("4"), let secondNumber = Int("42"), firstNumber < secondNumber && secondNumber < 100 {
    print("\(firstNumber) < \(secondNumber) < 100")
}
// 輸出 "4 < 42 < 100"

if let firstNumber = Int("4") {
    if let secondNumber = Int("42") {
        if firstNumber < secondNumber && secondNumber < 100 {
            print("\(firstNumber) < \(secondNumber) < 100")
        }
    }
}
// 輸出 "4 < 42 < 100"

注意: 在 if 條件語(yǔ)句中使用常量和變量來(lái)創(chuàng)建一個(gè)可選綁定,僅在 if 語(yǔ)句的句中(body)中才能獲取到值

隱式解析可選類(lèi)型

如上所述,可選類(lèi)型暗示了常量或者變量可以“沒(méi)有值”。可選可以通過(guò)if 語(yǔ)句來(lái)判斷是否有值,如果有值的話(huà)可以通過(guò)可選綁定來(lái)解析值
有時(shí)候在程序架構(gòu)中,第一次被賦值之后,可以確定一個(gè)可選類(lèi)型總會(huì)有值。在這種情況下,每次都要判斷和解析可選值是非常低效的,因?yàn)榭梢源_定它總會(huì)有值

這種類(lèi)型的可選狀態(tài)被定義為隱式解析可選類(lèi)型
把想要用作可選的類(lèi)型的后面的問(wèn)號(hào)(String?)改成感嘆號(hào)(String!)來(lái)聲明一個(gè)隱式解析可選類(lèi)型

當(dāng)可選類(lèi)型被第一次賦值之后就可以確定之后一直有值的時(shí)候,隱式解析可選類(lèi)型非常有用。隱式解析可選類(lèi)型主要被用在 Swift 中類(lèi)的構(gòu)造過(guò)程中

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

let possibleString: String? = "An optional string."
let forcedString: String = possibleString! // 需要感嘆號(hào)來(lái)獲取值

let assumedString: String! = "An implicitly unwrapped optional string."
let implicitString: String = assumedString  // 不需要感嘆號(hào)

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

如果你在隱式解析可選類(lèi)型沒(méi)有值的時(shí)候嘗試取值,會(huì)觸發(fā)運(yùn)行時(shí)錯(cuò)誤。和你在沒(méi)有值的普通可選類(lèi)型后面加一個(gè)驚嘆號(hào)一樣
你仍然可以把隱式解析可選類(lèi)型當(dāng)做普通可選類(lèi)型來(lái)判斷它是否包含值:

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

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

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

如果一個(gè)變量之后可能變成nil的話(huà)請(qǐng)不要使用隱式解析可選類(lèi)型。如果你需要在變量的生命周期中判斷是否是nil的話(huà),請(qǐng)使用普通可選類(lèi)型。

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

你可以使用swift標(biāo)準(zhǔn)庫(kù)assert(_:_:file:line:) ,函數(shù)來(lái)寫(xiě)一個(gè)斷言。向這個(gè)函數(shù)傳入一個(gè)結(jié)果為 true 或者 false 的表達(dá)式以及一條信息,當(dāng)表達(dá)式的結(jié)果為 false 的時(shí)候這條信息會(huì)被顯示

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

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

最后編輯于
?著作權(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ù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,622評(píng)論 6 544
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,716評(píng)論 3 429
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 178,746評(píng)論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 63,991評(píng)論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,706評(píng)論 6 413
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 56,036評(píng)論 1 329
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,029評(píng)論 3 450
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 43,203評(píng)論 0 290
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,725評(píng)論 1 336
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,451評(píng)論 3 361
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,677評(píng)論 1 374
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,161評(píng)論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,857評(píng)論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 35,266評(píng)論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 36,606評(píng)論 1 295
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 52,407評(píng)論 3 400
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,643評(píng)論 2 380

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