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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

Swift4.1第二章 The Basics

發(fā)布時間:2024/4/17 编程问答 62 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Swift4.1第二章 The Basics 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

Swift語言開發(fā)指南

基礎(chǔ)部分

Swift是一門新的開發(fā)語言,它可以在iOS、macOS watchOS以及tvOS系統(tǒng)環(huán)境下進(jìn)行應(yīng)用的開發(fā)。

Swift提供了它自己的C和Objective-C語言的所有基本數(shù)據(jù)類型。包括用于描述整數(shù)的Int,描述浮點型的Double和Float,描述布爾值的Bool以及描述文本數(shù)據(jù)的String。Swift也提供了三個主要的集合類型。比如集合類型中描述的的數(shù)組、集合、和字典。

和C語言一樣,Swift用變量來存儲和引用一個已經(jīng)被聲明過名字的值。Swift同樣能夠使用不可變數(shù)據(jù)類型的值。這些不能改變的值被稱為常量,它比C語言中的常量更加強(qiáng)大。當(dāng)你在使用不可變的值的時候,常量能夠使你的代碼變得安全整潔。

除了一些熟悉的類型之外,Swift還提供了Objective-C沒有的高級類型,比如說:元組。元組能夠讓你創(chuàng)創(chuàng)建和傳遞一組數(shù)據(jù)。函數(shù)中返回多個值的時候你可以用元組作為單個復(fù)合值來接收。

Swift也提供了一些可選類型,它能夠處理值缺失的情況。可選值的意思是說:這里有一個值,它等于X或者它沒有值。使用可選類型的之后就像使用Objective-C中的空指針一樣,但是它的使用不僅僅局限于類,可以是任意類型。和Objective-C中的空指針相比來說,可選類型可不僅僅是安全和更具表現(xiàn)力那么簡單,它們是Swift最強(qiáng)大功能中的核心。

Swift是一門安全類型的語言。這意味著這門語言可以幫你弄明白你所使用的值是什么類型的。如果你的代碼中需要的是String,當(dāng)你用Int來給它賦值的時候,類型安全會阻止你這么做。同樣的,如果你意外的將可選字符串傳遞給非可選字符串那么類型安全會阻止你這么做。類型安全可以幫你在開發(fā)過程中盡早的捕獲和修正錯誤。

常量和變量

常量和變量都需要用一個別名(比如說maximumNumberOfLoginAttempts或者welcomeMessage)以及一個特殊的數(shù)據(jù)類型的值(比如說數(shù)字10和字符串hello)來來進(jìn)行關(guān)聯(lián).常量的值一旦被初始化設(shè)置了之后就不能發(fā)生改變了,而變量則可以在未來給它賦不同的值。

常量和變量的聲明

常量和變量在使用之前都是要經(jīng)過聲明的。你可以用關(guān)鍵詞let來修飾一個常量,用var關(guān)鍵詞來修飾一個變量。下面的例子是通過對常量和變量的使用來模擬一個用戶嘗試登錄次數(shù)的場景。

let maximumNumberOfLoginAttempts = 10 var currentLoginAttempts = 0

這段代碼可以被解讀為:
聲明一個新的名字為maximumNumberOfLoginAttempts的常量,它的值為10。然后聲明一個新的名為currentLoginAttempts的變量,它的初始值為0.
在這個例子中,最大允許嘗試登錄次數(shù)被聲明為一個常量,因為最大的嘗試登錄次數(shù)不能被修改。當(dāng)前的嘗試登錄次數(shù)被聲明為一個變量,因為這個次值會隨著嘗試登錄失敗的次數(shù)的增加而增加。
你可以連續(xù)聲明幾個常量或者變量在同一行中,他們之間用逗號隔開。

var x = 0.0,y = 0.0,z = 0.0

注意:
如果你的代碼中使用的值是不會發(fā)生改變的那么用let關(guān)鍵字來聲明。如果聲明的值是需要發(fā)生改變的那么用var關(guān)鍵字來聲明。

類型標(biāo)注

在聲明常量和變量的時候你可以為它提供一個類型標(biāo)注,它可以很清楚的告訴編輯器常量和變量以什么樣的數(shù)據(jù)類型被存儲。在常量和變量添加類型標(biāo)注的時候在命名之后加一個冒號以以及空格,然后加上類型的名稱。

下面的這個例子里給出一個叫做welcomeMessage變量的類型標(biāo)注,它表明了這個變量被存儲為一個String類型的值。

var welcomeMessage: String

在聲明的時候冒號的意思是“...類型的”,因此上面的代碼可以這樣來理解:

聲明一個類型為String的變量welcomeMessage。

類型字符串的意思是可以存儲任意值的字符串,可以把它理解為有存儲功能的"事物類型"。

變量welcomeMessage可以被賦值為任意的字符串而不報錯。

welcomeMessage = "Hello"

你可以在一行定義多個同一種類型的變量,用逗號隔開在最后一個變量后面添加冒號和類型標(biāo)注。

var red,green,blue:Double

注意:
在實際開發(fā)中我們很少需要給常量/變量來寫類型標(biāo)注,如果在定義常量/變量的時候給了一個初始值,那么Swift可以幫我們推斷出常量/變量的類型。具體請參考類型和安全判斷。在上面定義的變量welcomeMessage中,我們沒有給它賦初值,因此變量welcomeMessage的類型是從類型標(biāo)注里判斷的,而不是從它初始值判斷的。

常量和變量的命名

常量和變量的名字可以包含任意字符串,當(dāng)然也包括了Unicode
字符。

let π = 3.14159 let 你好 = "你好世界" let ?? = "dogcow"

常量和變量的命名不能包含空格字符,數(shù)學(xué)符號,箭頭,保留的(或者非法的)Unicode碼位,連線與制表符。也不能夠用數(shù)字開頭,盡管數(shù)字可能在名稱的其他地方可以使用。

一旦你為常量和變量聲明一個確定的類型之后,你不能夠再聲明一個相同名字類型的常量/變量,并且也不能夠改變它所存儲的類型,當(dāng)然你也不能夠?qū)ΤA亢妥兞康幕Q操作。

注意:
如果你需要使用和Swift保留關(guān)鍵字相同的名稱作為常量和變量名。你可以使用關(guān)鍵字反引號(`)將關(guān)鍵字包起來作為它的名字,不到萬不得已的時候,建議你不要使用關(guān)鍵字來作為常量和變量的名字。

你可以改變一個變量的值為另外一種相同類型的值,在下面的例子中,friendWelcome的值從hello!變?yōu)锽onjour!。

var friendWelcome = "hello !" friendWelcome = "Bonjour !" // friendWelcome is now "Bonjour!"

和變量不同的是常量在初始化設(shè)置以后就不能夠發(fā)生改變了。當(dāng)你改變常量值的時候,編譯器會報錯。

let languageName = "Swift" languageName = "c++" //Cannot assign to value: 'languageName' is a 'let' constant // 這里是一個編譯錯誤,languageName 不能夠被改變.

打印出常量和變量

你可以用print(_:separator:terminator:)?這個函數(shù)打印出常量和變量的當(dāng)前值。

print(friendWelcome) // 打印出 friendWelcome 的值

?print(_:separator:terminator:)函數(shù)是一個在全局的指定區(qū)域打印出一個甚至更多值的的函數(shù)。例如在Xcode里面,print(_:separator:terminator:)是在xcode的控制臺輸出的。separator和terminator參數(shù)都有默認(rèn)值,因此你當(dāng)你調(diào)用函數(shù)的時候可以省略掉它們。函數(shù)默認(rèn)通過換行符來結(jié)束當(dāng)前行。如果不想換行,可以默認(rèn)添加一個空的字符串來代替,例如:print(someValue, terminator: "").如果想了解更多關(guān)于參數(shù)的信息,可以查看默認(rèn)參數(shù)。

Swift用字符串插值的方式把常量名和變量名當(dāng)做占位符加入到長字符串中,Swift會把常量和變量的值替換掉這些占位符。把常量和變量名放到括號里面,并在括號前面加上反斜杠來轉(zhuǎn)義。

print("The currenct value of firendlyWelcome is \(friendWelcome)") // 打印出當(dāng)前firendlyWelcome的值

注意:
字符串插值所有能用的選項在這里能找到。

注釋

把你代碼里不用執(zhí)行的文本用打上注釋作為注解或者一個標(biāo)記來提醒你自己。在swift中,編譯器會忽略掉注釋的編譯。

在swift中注釋和在c語言的注釋十分相似。單行的注釋用//來表示。

// This is a comment.

多行注釋以/*開始,以*/結(jié)尾。

/*This is also a comment.but is written over multiple lines. */

和C語言中多行注釋不同的是,swift中多行注釋是可以進(jìn)行嵌套的。你可以寫一個嵌套的多行注釋用/*開始 ,然后添加第二個多行注釋以/*開始以*/結(jié)束。最后用*/來結(jié)束第一個多行注釋。

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

注釋的多行嵌套使得你在注釋大量代碼塊的時候更加便捷和容易,即使代碼里已經(jīng)存在多行注釋也沒有影響。

分號

和其他編程語言不同的是,在swift中,在代碼的結(jié)尾,不需要你寫分號(;)當(dāng)然,你也可以按照你的習(xí)慣來添加分號。有一種情況是必須要添加分號的,那就是在一行中執(zhí)行多個語句

let cat = "?";print(cat) // print "?"

整數(shù)

整數(shù)就是沒有小數(shù)的數(shù)字,比如說:42和-23.整數(shù)可以是有符號的類型(正數(shù),負(fù)數(shù)和0),也可以是無符號的類型(正數(shù)和0)。

swift為我們提供了8位,16位,32位,以及64位的無符號和有符號的整數(shù)。這些整數(shù)的命名規(guī)則和c語言類似。比如說:有無符號的8位整數(shù)UInt8和有符號的32位整數(shù)Int32。像swift中的其他類型一樣,整數(shù)類的命名都是大寫字母開頭。

整數(shù)的范圍

你可以通過訪問整數(shù)的最大值屬性和最小值屬性在確定他們的范圍。

let minValue = UInt8.min // UInt8的最小值為0 let maxValue = UInt8.max // UInt8的最大值為2 print("minValue of UInt8 is \(minValue) and maxValue of UInt8 is \(maxValue)。")

這些屬性的值表明了這種類型數(shù)據(jù)只能在規(guī)定范圍內(nèi)進(jìn)行操作(就像上面UInt8的例子),因此同種類型的數(shù)據(jù)可以在表達(dá)式中一起使用。

Int

在大多數(shù)情況下,在寫代碼的過程中我們并不需要指定一個長度給Integer。Swift提供了另外一個整數(shù)類型的數(shù)據(jù)Int,它的長度和原生平臺的字節(jié)數(shù)相同。

  • 在32位的平臺上,Int的長度和Int32一致。
  • 在64位的平臺上,Int的長度和Int64一致。
  • 如果你不需要為整型添加特殊的長度處理,用默認(rèn)的Int來實現(xiàn)代碼就行。這可以提高代碼的一致性和可復(fù)用性。甚至是在32位的平臺上,他能夠儲存在-2,147,483,648和2,147,483,647范圍之間的數(shù)據(jù),在很多時候這個范圍內(nèi)的數(shù)據(jù)已經(jīng)很大了。

    UInt

    swift也為我們提供了無符號類型的整型數(shù)據(jù)。UInt和原生平臺有著相同長度的字節(jié)數(shù)。

  • 在32位的平臺上,UInt的長度和UInt32一致。
  • 在64位的平臺上,UInt的長度和UInt64一致。
  • 注意:
    盡量不要使用UInt,除非你真的需要存儲一個和當(dāng)前原生平臺長度相同的字節(jié)數(shù)的無符號整數(shù)時候,如果不是這種情況,建議你最好使用Int,即使你要存儲的對象已知是非負(fù)的。統(tǒng)一使用Int提高了代碼的一致性和可復(fù)用性。避免在不同的數(shù)據(jù)類型進(jìn)行轉(zhuǎn)換,并且匹配數(shù)字的類型進(jìn)行判斷,具體請參考類型安全和類型推斷。

    浮點型數(shù)據(jù)

    所謂浮點型數(shù)據(jù)就是帶有小數(shù)部分的數(shù)據(jù)。比如:3.14258,0.1和-273.15。

    浮點型所代表值得范圍要比整型要更大,它能夠儲存比整型更小或者更大的值。Swift提供了兩種有符號的浮點數(shù)類型。

  • Double類型代表的64位浮點型數(shù)據(jù)。
  • Float類型代表的32位浮點型數(shù)據(jù)。
  • 注意:
    Double類型精度至少為小數(shù)點后15位,Float類型的精確度僅僅是小數(shù)點后6位。
    你可以根據(jù)自己編程的需要值的范圍選擇是Double類型還是Float類型,如果兩種條件都滿足,優(yōu)先選擇Double。

    類型安全和類型判斷

    Swift是一個類型安全的語言,類型安全的語言可以讓你清楚的知道你所處理的代碼值的類型。如果你代碼中需要的是String,那么。你如果給它賦值為Int類型的數(shù)據(jù),那么編譯器就會報錯。

    因為Swift是類型安全的語言,所以它在編譯的時候會對代碼進(jìn)行類型的檢查。這在開發(fā)過程中能夠幫助你盡可能早的發(fā)現(xiàn)和解決問題。

    當(dāng)你在處理不同類型數(shù)據(jù)的時候,類型檢查能夠幫助避免一些問題。然而,這并不意味著你在每次聲明常量或者變量的時候都需要顯示指定類型。如果你沒有指定顯示類型,那么swift會使用類型判斷來為你選擇合適的類型。類型判斷確保了編譯器在編譯代碼的時候通過檢查你賦的值自動推斷出表達(dá)式的類型。

    因為有了類型判斷,和c或者c++相比來說,swift很少需要你進(jìn)行類型聲明。常量和變量雖然需要來明確類型,但是大部分工作并不需要你來完成,編譯器已經(jīng)為你完成了。

    當(dāng)你聲明一個常量或者變量賦初值的時候類型判斷變非常有用。在你聲明常量或者變量的時候,賦給它們一個字面量(literal?value或者literal)就能夠讓編譯器自己來進(jìn)行類型判斷。(所謂字面量就是直接出現(xiàn)在代碼中的值,比如下面例子中的42和3.14159。)

    例如:如果你給一個新的常量用字面量的形式給它賦值為42沒有聲明它的數(shù)據(jù)類型,Swift能推斷出你要給常量賦一個Int類型的數(shù)據(jù),因為你在初始化的時候給它賦值了一個像整型的數(shù)字。

    let meaningOfLife = 42 // meaningOfLife will be inferred to be of type Int 這里常量meaningOfLife 會被便以及推斷為一個整型

    同理,如果你沒有給浮點類型的數(shù)據(jù)標(biāo)記類型,那么Swift會默認(rèn)類型的Double

    let pi = 3.14159 // pi will be inferred to be of type Double 這里常量pi會被默認(rèn)推斷為DoubleL類型的數(shù)據(jù)。

    當(dāng)swift在推斷浮點型數(shù)據(jù)的時候,它會默認(rèn)推斷為Double類型而不是Float類型。

    如果你在一個表達(dá)式中用整型和浮點型混合計算的時候,在上下文中會被swift推斷為Double類型。

    let anotherPi = 3 + 0.14159 // anotherPi will be inferred of type Double 這里常量anotherPi會被swift推斷為Double類型的數(shù)據(jù)。

    初始值3沒有給顯式聲明類型,并且在表達(dá)式中出現(xiàn)了一個浮點類型的字面量,所以表達(dá)式被推斷為Double類型。

    數(shù)值型字面量

    整數(shù)類型的字面量可以被寫作:

  • 一個十進(jìn)制數(shù),沒有前綴
  • 一個二進(jìn)制數(shù),前綴是0b
  • 一個八進(jìn)制數(shù),前綴是0o
  • 一個十六進(jìn)制數(shù),前綴是0X
  • 下面所有的整數(shù)型字面量都是代表十進(jìn)制的值17

    let decimalInteger = 17 let binaryInteger = 0b10001// 二進(jìn)制的17 2*2*2*2+1 let octalInteger = 0o21 // 八進(jìn)制的17 2*8+1*1 let hexadecimalInteger = 0x11 // 十六進(jìn)制的17 16*1+1

    浮點型的字面量可以是十進(jìn)制(沒有前綴),也可以是十六進(jìn)制的(帶有前綴)。在小數(shù)的兩遍必須是十進(jìn)制的值值(或者十六進(jìn)制有前綴的值)。十進(jìn)制的浮點數(shù)可以有一個可選的指數(shù)(exponent)。通常用大寫的或者小寫的e來表示,十六進(jìn)制的浮點數(shù),通常用大寫或者小寫的p來表示。

    如果一個十進(jìn)制的指數(shù)為exp,那么這個數(shù)相當(dāng)于基數(shù)和10^exp的乘積.
    例如:
    1.25e2表示的是1.25*10^2或者125.0。
    1.25e-2表示的是1.25*10^-2或者0.0125。
    如果一個有前綴的十六進(jìn)制的指數(shù)為exp,那么這個數(shù)相當(dāng)于基數(shù)和2^exp的乘積。
    例如:
    0xFp2表示的是15*2^2或者60.0。
    0xFp-2表示的是15*2^-2或者3.75。
    下面的浮點型的字面量都等價于十進(jìn)制的值12.1875。

    //浮點類型的十進(jìn)制的12.1875 let decimalDouble = 12.1875 let exponentDouble = 1.21875e1 let hexadecimalDouble = 0xC.3p0 //計算方式:0x代表16進(jìn)制C代表12后面.3代表小數(shù) 所以整數(shù)部分應(yīng)該是應(yīng)該是12*(16^0)+0.3*(16^-1) 后面的p代表指數(shù),以2為底。所以完整表達(dá)式為(12*(16^0)+0.3*(16^-1))*(2^0)

    數(shù)字類型的字面量添加額外的標(biāo)記能夠使它們看起來更容易閱讀。整數(shù)和浮點型都可以添加額外的零加上下劃線來增強(qiáng)可閱讀性,并且不會影響字面量的值。

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

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

    即使常量和變量你已經(jīng)知道它們是非負(fù)的,你也可以在代碼中用Int類型來修飾它們。使用默認(rèn)整數(shù)數(shù)據(jù)類型保證了常量和變量可以被復(fù)用并且能用來匹配整數(shù)字面量的類型推斷。

    當(dāng)我們做特殊的任務(wù)時候才會對整型類型做類型指定,比如:需要處理的外部的長度明確了數(shù)據(jù)或者為了性能優(yōu)化、內(nèi)存占用等等。使用顯式指定長度的類型可以及時的發(fā)現(xiàn)值的溢出并且還能標(biāo)記我們在處理的是特殊的數(shù)據(jù)。

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

    不同類型的整數(shù)可以保存不同范圍的常量和變量。Int8類型的整數(shù)可以存儲數(shù)據(jù)的范圍是-128到127。無符號整型的可以存儲常量和變量的范圍是0到255。如果數(shù)字超出了常量和變量對應(yīng)值的范圍,編譯的時候會報錯。

    let cannotBeNegative:UInt8 = -1 //不在UInt8值范圍內(nèi)報錯 let tooBig:Int8 = Int8.max + 1 //超出Int8值范圍內(nèi)報錯

    因為不同數(shù)據(jù)類型能夠存儲數(shù)據(jù)的范圍是不一樣的,在進(jìn)行類型轉(zhuǎn)換的時候你必須選擇一個合適的數(shù)據(jù)類型進(jìn)行轉(zhuǎn)換。這種轉(zhuǎn)換方式能夠讓你的代碼的意圖更明顯,并且能夠防止你在隱式轉(zhuǎn)換中遇到的錯誤。

    在轉(zhuǎn)換一個特殊的數(shù)字類型到另一個類型的時候,你需要重新初始化一個你需要的目標(biāo)數(shù)據(jù)。在下面的例子中,常量twoThousand是一個UInt16類型的數(shù)據(jù),和它一起需要轉(zhuǎn)換的數(shù)據(jù)類型是UInt8,它們兩個不能夠直接相加,因為他們兩個類型不一樣。
    我們可以用UInt16(one)來創(chuàng)建一個UInt類型的數(shù)據(jù)用one的值進(jìn)行初始化。用初始化的數(shù)據(jù)類代替原始數(shù)據(jù)。

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

    因為等式兩邊的類型都是UInt16,所以兩者等式操作是被允許的。輸出的常量(twoThousandAndOne)的數(shù)據(jù)類型被swift推斷為UInt16,因為它是兩個UInt16的常量相加而來的。

    SomeType(ofInitialValue)調(diào)用的是swift構(gòu)造器并傳入一個初始值的默認(rèn)方法。在語言的內(nèi)部,UInt16有一個構(gòu)造器可以接收一個UInt8類型的數(shù)據(jù)。這個構(gòu)造的作用是通過已經(jīng)存在的UInt8類型的數(shù)據(jù)初始化一個UInt16類型的數(shù)據(jù)。需要注意的是:你并不能任意的傳入值,只有在傳入UInt16內(nèi)部有對應(yīng)構(gòu)造器的值。不過你可以擴(kuò)展現(xiàn)有的類型,讓它來接收其他類型的值(包括自定義的類型),具體請參考擴(kuò)展。

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

    在進(jìn)行整數(shù)和浮點數(shù)類型轉(zhuǎn)換的時候一定要指定類型。

    let three = 3 let pointOneFourOneFiveNine = 0.14159 let pi = Double(three) + pointOneFourOneFiveNine // pi等于3.14159,被Swift推斷為double類型

    在這里,常量three被當(dāng)做一個Double類型的數(shù)據(jù)來創(chuàng)建,因此+兩邊應(yīng)為相同的類型。如果這里沒有進(jìn)行轉(zhuǎn)化,那么+(加號運算符)是不被允許使用的。
    浮點型的數(shù)據(jù)和整型一樣可以互相轉(zhuǎn)換。整型可以使用Double和Float進(jìn)行初始化。

    let integerPi = Int(pi) //這里integerPi等于3,被Swift推斷為Int類型。

    上面我們使用浮點型數(shù)據(jù)進(jìn)行初始化一個整型數(shù)據(jù)的時候,我們發(fā)現(xiàn)浮點值被截斷了。這意味著4.75變成了4,-3.9被截斷為-3。
    注意:
    結(jié)合數(shù)字型的常量和變量的規(guī)則和數(shù)字字面量的規(guī)則是不同的,在字面量3可以和直接和字面量0.14159相加,因為數(shù)字型的字面量他們本身值是沒有特定類型的。它們的類型只有在編譯需要計算值的時候才會被推斷。

    類型別名

    類型別名是給已經(jīng)存在的一個數(shù)據(jù)類型添加一個可選的名字。你可以用關(guān)鍵字typealias來定義這是一個類型別名。

    當(dāng)你想給現(xiàn)有的類型添加一個有意義的名字的時候,類型別名顯得特別的有用。我們假設(shè)你正在處理特定長度的外部資源的數(shù)據(jù)的時候:

    typealias AudioSample = UInt16

    當(dāng)你定義過一個類型別名的時候,你可以在任意一個地方像使用原始名一樣來使用這個別名。

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

    在這里,AudioSample被定義成一個值為UInt16的別名。正因為這是一個別名,所以我們調(diào)用AudioSample.min實際上就是調(diào)用UInt16.min這個函數(shù),這樣為變量maxAmplitudeFound提供了一個初始值0。

    布爾值

    Swift 有一個基礎(chǔ)的布爾類型叫做Bool,布爾的值是邏輯上的值,因此只有真和假。Swift為我們提供了兩個bool常量true 和false。

    let ornagesAndOrange = true let turnipsAndDelicious = false

    ornagesAndOrange和turnipsAndDelicious被推斷為Bool因為他們是由Bool字面量初始化來的。就像上面提到的Int和Double類型,當(dāng)在聲明的時候你只需要設(shè)置一下他們的值true 或false不需要聲明常量或者變量的類型。當(dāng)初始化常量或者變量的時候如果要賦值的類型是已知的,就可以觸發(fā)便以及的類型推斷,這使得Swift的代碼更加簡潔和易讀。

    當(dāng)你在寫條件語句比如if語句的時候,布爾值顯得更加有用。

    if turnipsAndDelicious {print("Mmm, tasty turnips!") } else {print("Eww, turnips are horrible.") } // 這里打印的是:Eww, turnips are horrible.

    關(guān)于條件語句,比如if語句,可以參考控制流
    如果你在使用Bool值的時候賦了其他類型的值,那么swift因為類型安全就會報錯。下面的例子中就會報編譯的錯誤。

    let i= 1 if i { // 這個例子不會編譯成功,會報錯(報錯原因是 判斷的值不是bool類型) }

    然而,下面的例子是合法的:

    let i = 1 if i == 1 {// 這個例子能編譯成功不報錯。因為這里i == 1 是一個判斷語句 }

    因為等式i == 1的結(jié)果是一個Bool類型的值,所以第二個例子能夠通過類型檢查。像i == 1這樣類型的比較,參考 基本操作符。
    和swift中其他類型安全的例子一樣,這個方法避免了一些偶然的錯誤并且保證了代碼的目的總是清晰的。

    元組

    元組(Truples)就是把多個值組合成一個復(fù)合值。元組中的成員并不一定是相同類型的數(shù)據(jù),它們可以是任意類型的數(shù)據(jù)。
    在這個例子中(404,"Not Found")就是一個代表HTTP狀態(tài)碼的元組。HTTP狀態(tài)碼是當(dāng)你請求網(wǎng)頁的時候,web服務(wù)器返回的一個特殊值。如果請求的網(wǎng)頁不存在就會返回狀態(tài)碼404 NOT Found。

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

    (404,"Not Found") 這個元組把Int和String的值放到一起組合起來表示HTTP請求的狀態(tài)碼的兩部分:一個數(shù)組和另外一個可讀的描述。它被描述為一個類型為(Int,String)的元組。

    你可以把任意順序的類型組合為一個元組,這個元組可以你需要的任意類型的數(shù)據(jù)。你可以創(chuàng)建一個類型為(Int,Int,Int)或者(String,Bool)或者其他的任何你想創(chuàng)建任意組合的元組。

    你可以將元組的內(nèi)容分解為單獨的常量或者變量,然后你就可以正常使用它們了。

    let (statusCode, statusMessage) = http404Error print("The status code is \(statusCode)") //輸出的狀態(tài)碼為 404 print("The status message is \(statusMessage)") // 輸出的狀態(tài)描述為 Not Found

    如果你只需要元組中的其中一個值,那么分解的時候你可以用_將不需要的部分省略掉。

    let (justTheStatusCode,_) = http404Error print("The status code is \(justTheStatusCode)") // 輸出的狀態(tài)碼為 404

    此外,你還可以用下標(biāo)來訪問元組中的某個值,元組中的下標(biāo)從0開始。

    print("The status code is \(http404Error.0)") //輸出的狀態(tài)碼為 404 print("The status message is \(http404Error.1)") // 輸出的狀態(tài)描述為 Not Found

    你可以在定義元組的時候給單個元組進(jìn)行命名

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

    當(dāng)元組中的元素命名后,你可以通過名字來獲取對應(yīng)的元素的值。

    print("The status code is \(http200Status.statusCode)") 輸出的狀態(tài)碼為 200 print("The status message is \(http200Status.description)") // 輸出的狀態(tài)描述為 OK

    元組在用作函數(shù)返回值的時候顯得尤為重要。已給獲取網(wǎng)頁請求狀態(tài)地方函數(shù)可以會返回一個(Int,String)元組來描述網(wǎng)絡(luò)請求的狀態(tài)。這和只能返回一個值進(jìn)行比較來說。一個包含兩個不同類型值的元組返回地方信息更有用。了解更多請參考函數(shù)與返回值。

    注意:

    元組在組織臨時值的時候很有用,它們并不適合用到復(fù)雜的數(shù)據(jù)結(jié)構(gòu)里。如果你的數(shù)據(jù)結(jié)構(gòu)不是臨時的使用,那么請使用類或者結(jié)構(gòu)體而不是用元組。了解更多,請參考類與結(jié)構(gòu)體。

    可選類型

    當(dāng)處理值缺失情況的時候,你可以用可選類型來表示。可選類型表明有兩種可能性:或者有值,你可以解析這個可選類型來訪問這個值。或者這個值不存在。
    注意:
    在C語言和Objective-C語言中不存在可選類型這個概念。在Objective-C語言中最接近的是一個方法中不要么返回一個對象,要么返回nil,nil表示缺少一個合法的對象。然而,這只對對象起作用,對于結(jié)構(gòu)體,基本的C數(shù)據(jù)類型以及枚舉值都不起作用。對于這些類型,Objective-C方法中一般會返回一個特殊值(比如NSNotFound)來暗示值的缺失。這種方法假設(shè)方法的調(diào)用者知道并對這些特殊值進(jìn)行判斷。然而,Swift的可選類型讓你明白任意類型額值缺失,并不需要一個特殊的常量。

    這里有一個關(guān)于可選值是怎么被用作當(dāng)做缺省值的例子,Swift中整型中有一個構(gòu)造器,作用是將一個String類型的值轉(zhuǎn)換成一個Int類型的值。然而,并不是所有的字符串都能夠轉(zhuǎn)化為整型。字符串123可以被轉(zhuǎn)化為整型123,但是字符串Hello,world不能被轉(zhuǎn)化為整型。

    下面的例子中使用這種便利構(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;類型的值也可能不包含。(不能包含其他的類型,比如說Bool類型的值或者String類型的值,它只能是Int類型,或者不存在這個類型。)

    nil

    你可以給一個不存在的可選類型的變量賦值為nil:

    var serverResponseCode:Int? = 404 // serverResponseCode中包含了一個可選的Int類型的值404 serverResponseCode = nil // 這里serverResponseCode的值為nil(值不存在)

    注意:
    你不能夠把nil用在非可選的變量和常量上。如果你的代碼中存在常量或者變量值缺省的情況,那么在聲明的時候就聲明為可選變量或者常量。

    如果你不提供可選類型的變量的初始值,那么變量會自動設(shè)置為nil。

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

    注意:
    Swift中的nil和Objective-C中的nil意義不一樣。在Objective-C中,nil是一個指向不存在對象的一個指針。在Swift中,nil不是一個指針,它是一個確定類型的值。任何類型的可選狀態(tài)都可以被設(shè)置為nil,不僅僅是對象類型的數(shù)據(jù)。

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

    你可以使用if語句和nil來判斷比較已給可選值是否包含值。你可以使用(==)以及(!=)等于以及不等于兩個操作符來判斷一個可選值是否包含值。

    如果一個可選類型是有值的,那么它被認(rèn)為不等于nil。

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

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

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

    更多關(guān)于if條件語句的介紹,請參考控制流。

    注意:
    使用!來獲取一個不存在的值可能會導(dǎo)致運行時的錯誤。在進(jìn)行強(qiáng)制類型解析!的時候要注意,確保可選類型一定要包含一個不為nil的值。

    可選綁定

    使用可選綁定來找出一個可選類型是否包含值,如果包含,如果包含就把值賦給一個臨時變量或者常量。可選綁定可以用在if和while等條件語句中,這條語句不僅僅可以判斷可選類型中是否有值,同時也可以將可選類型中的值賦給一個常量或者變量。關(guān)于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)被可選類型包含的值初始化過,這里就不需要再變量的后面添加!來進(jìn)行強(qiáng)制解析獲取它的值了。在這個例子中,actualNumber只是被用來輸出轉(zhuǎn)換的結(jié)果。

    常量和變量都可以使用可選類型綁定。如果你想在if的第一個分支語句中使用actualNumber,那么你可以把判斷條件改為if var actualNumber 這里就把可選類型中包含的值就被賦值給一個變量而不是一個常量。
    你可以在if語句中使用多個可選綁定或者Bool類型來作為條件判斷,它們之前用逗號隔開。如果可選類型中任意一個值為nil或者Bool類型中判斷結(jié)果為false,那么整個if語句的條件判斷就會被認(rèn)為是false。下面例子中的if語句是等價的:

    if let firstNumber = Int("4"),let secondNumber = Int("42"),firstNumber < secondNumber && secondNumber < 100 {print("\(firstNumber) < \(secondNumber) < 100") } // 打印的結(jié)果是:4 < 42 < 100 if let firstnumber = Int("4") {if let secondnumber = Int("42") {if firstnumber < secondnumber && secondnumber < 100 {print("\(firstnumber) < \(secondnumber) < 100")}} } // 打印的結(jié)果是:4 < 42 < 100

    注意:
    在if語句中創(chuàng)建的常量和變量的可選綁定,只能在body中使用。相反,在guard語句中創(chuàng)建的常量和變量的可選綁定,只有在guard語句之外能夠取到值,請參參考提前退出。

    隱式解析可選類型

    就像上面描述的一樣,可選類型暗示了常量和變量可以沒有值,可選類型通過if語句來判斷是否有值,如果有值的話可以通過可選綁定來進(jìn)行值的解析。

    有時候在程序的結(jié)構(gòu)中,在第一次被賦值以后,可以確定一個可選的類型總是有值。在這種情況下,每次都進(jìn)行判斷和解析可選值是很低效的,因為可以確定這個值是總是存在的。
    這種類型的可選狀態(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)對程序運行過程中可能會出現(xiàn)的錯誤情況。

    與可選值不一樣的是,運用值的存在與缺失來表達(dá)函數(shù)執(zhí)行的成功與失敗,錯誤處理可以推斷出失敗的原因。并可以傳播到程序的其他地方。

    當(dāng)一個函數(shù)遇到出現(xiàn)錯誤條件的時候,它能拋出錯誤。調(diào)用函數(shù)方法的地方能拋出異常并合理的響應(yīng)。

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

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

    Swift會自動將錯誤傳播到當(dāng)前的范圍直到它們被catch句子來處理。

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

    一個do語句創(chuàng)建了一個新的作用域,它允許錯誤被傳遞到一個或者多個catch語句中。
    這是一個如何運用錯誤處理來應(yīng)對不同錯誤情況的例子:

    do {try makeASandwich()eatASandwich() } catch SandwichError.outOfCleardishes {washDishes() } catch SandwichError.missingTngredients(let ingredients) {buyGroceries(ingredients) }

    在這個例子中,makeASandwich()函數(shù)會拋出一個錯誤消息條件是如果沒有干凈的盤子或者某個原料的缺失。由于makeASandwich()可能會拋出錯誤,所以函數(shù)調(diào)用被包在了try語句中。將函數(shù)包在一個do語句中,那么任何被拋出的錯誤都會被傳播到catch語句中。
    如果沒有錯誤被拋出,那么eatASandwich()函數(shù)會被調(diào)用。如果一個匹配SandwichError.outOfCleardishes的錯誤被拋出,那么會執(zhí)行washDishes()這個函數(shù),如果異常SandwichError.missingTngredients被捕獲到,那么buyGroceries(_:)函數(shù)將會被調(diào)用,并且會使用catch所捕獲到的關(guān)聯(lián)值String作為參數(shù)。
    拋出,捕獲以及傳播錯誤等,會在錯誤處理的章節(jié)中說明。

    斷言和先決條件

    斷言和先決條件是在運行時進(jìn)行檢查的。你可以用它們來檢查在執(zhí)行后面代碼的之前是否一個必要的條件已經(jīng)滿足了。如果斷言或者先決條件中的bool值是true的時候,那么代碼會像往常一樣執(zhí)行。如果條件判斷為false,當(dāng)前程序的狀態(tài)是無效的,代碼的執(zhí)行會結(jié)束,你的app會被終止。

    你使用斷言和先決條件來表達(dá)你做的假設(shè)和你在編碼時候的希望執(zhí)行的方式。你可以將這些包含在代碼中。斷言幫助你在開發(fā)階段找到錯誤和不正確的假設(shè),先決條件幫助你在在生產(chǎn)環(huán)境中發(fā)現(xiàn)存在的問題。

    除了在運行時驗證你的期望值,斷言和先決條件也變成了你代碼中一種有用的文檔形式。和上面討論的錯誤處理不同,斷言和先決條件不是用來處理可以恢復(fù)或者可以預(yù)期的錯誤。因為一個斷言失敗表明了程序正在處于一個無效的狀態(tài),沒有辦法來捕獲一個失敗的斷言。

    使用斷言和先決條件不是一個能夠避免出現(xiàn)程序無效狀態(tài)的編碼方法。然而,如果一個無效狀態(tài)的程序產(chǎn)生快了。斷言可以強(qiáng)制檢查你的數(shù)據(jù)和程序狀態(tài),使程序按照預(yù)測中的被終止,并幫助我們更簡單的對這個問題進(jìn)行調(diào)試。一旦遇到無效的狀態(tài),程序就會被終止,防止無效的狀態(tài)對程序造成進(jìn)一步的傷害。

    斷言和先決條件的不同之處在于它們什么時候進(jìn)行檢測。斷言僅僅在調(diào)試的時候運行,但是先決條件不僅僅在調(diào)試的時候能運行在生產(chǎn)環(huán)境下也能運行。在生產(chǎn)環(huán)境下,斷言條件不會被評估。這意味著你可以在開發(fā)階段多使用斷言,這些斷言在生產(chǎn)條件下不會造成影響。

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

    你可以用Swift標(biāo)準(zhǔn)庫的函數(shù)assert(_:_:file:line:)來編寫一個斷言。
    你向這個函數(shù)傳入一個判斷結(jié)果為true和false的表達(dá)式以及一條錯誤情況下展示的信息。例如:

    let age = -3 assert(age >= 0,"A person's age can't be less than zero.") // 這個斷言會失敗 因為一個人的年齡不可能小于0(把斷言中的語句變?yōu)閍ge <= 0,就不會走這個斷言)

    在這個例子中,只有age >= 0為true也就是說age的值為非負(fù)數(shù)的時候,代碼才會繼續(xù)執(zhí)行。如果age的值為負(fù)數(shù),就像上面代碼中的一樣,那么,age >= 0 為false,斷言失敗,使得應(yīng)用被終止運行。

    你也可以省略掉斷言的提示信息,例如:當(dāng)斷言條件可能會重復(fù)執(zhí)行的時候

    assert(age >= 0)

    如果代碼已經(jīng)被檢查過,你可以使用函數(shù)assertionFailure(_:file:line:)來表明斷言失敗了。例如:

    if age > 10 {print("You can ride the roller-coaster or the ferris wheel.") } else if age > 0 {print("You can ride the ferris wheel.") } else {assertionFailure("A person's age can't be less than zero.") }

    強(qiáng)制執(zhí)行先決條件

    當(dāng)一個條件可能為假,但是繼續(xù)執(zhí)行下去要求條件必須為真的時候,需要使用先決條件。例如:使用先決條件來判斷下標(biāo)有沒有越界,或者來檢查是否將一個正確的參數(shù)傳給了函數(shù)。

    你可以使用函數(shù)precondition(_:_:file:line:)來寫一個先決條件。向這個函數(shù)傳入一個結(jié)構(gòu)為true或者false的表達(dá)式以及一條錯誤條件下顯示信息。例如:

    // 下標(biāo)的實現(xiàn) precondition(index > 0, "Index must be greater than zero.")

    你可以調(diào)用函數(shù)preconditionFailure(_:file:line:)來表明出現(xiàn)了一個錯誤,例如:switch的進(jìn)入了default分支,所有的有效輸入數(shù)據(jù)都應(yīng)該被其他分支所處理而不是默認(rèn)的default分支。
    注意:
    如果你使用不檢查的模式(-Ounchecked)進(jìn)行編譯,先決條件將不會進(jìn)行檢查。編譯器會假設(shè)所有的先決條件都是true,這將優(yōu)化你的代碼。然而致命的錯誤函數(shù)(_:file:line:)總是中斷執(zhí)行,無論你進(jìn)行什么樣的優(yōu)化設(shè)置。

    在設(shè)計原型和早期的開發(fā)階段你可以使用致命的錯誤函數(shù)(_:file:line:),這個階段只是對方法的聲明,
    但是沒有具體的實現(xiàn)。你可以在方法fatalError("Unimplemented")進(jìn)行具體實現(xiàn)。因為fatalError不會像斷言和先決條件那樣可以被優(yōu)化,所以你可以確保當(dāng)代碼執(zhí)行到一個沒有實現(xiàn)的方法是的時候,程序會被中斷。

    更多swift4.1翻譯請查看github。

    QQ技術(shù)交流群:214541576

    微信公眾號:shavekevin

    開發(fā)者頭條:

    熱愛生活,分享快樂。好記性不如爛筆頭。多寫,多記,多實踐,多思考。

    總結(jié)

    以上是生活随笔為你收集整理的Swift4.1第二章 The Basics的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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