Swift3.0P1 語法指南——基礎

原檔:https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/TheBasics.html#//apple_ref/doc/uid/TP40014097-CH5-ID309html

-----------------------------------------2016/07/01 3.0preview1版本----------------------------------ios

1、常量與變量

一、聲明安全

 let maximumNumberOfLoginAttempts = 10
 var currentLoginAttempt = 0

聲明一個名爲maximumNumberOfLoginAttempts的常量,賦值爲10。數據結構

聲明一個名爲currentLoginAttempt的變量,初始化值爲0。架構

也能夠在同一行中聲明多個變量:app

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

注:若是在代碼中,某個存儲的數據量不會再發生變化,則老是把這個量用let關鍵字聲明爲常量。只用變量來表示那些須要改變值的量。less

二、類型標註函數

1 var welcomeMessage: String
2 var red, green, blue: Double

Swift能夠根據賦的初值來推斷出變量或常量的類型。當你沒有賦予初值的時候,則務必要聲明變量或常量的類型。性能

三、命名優化

常量和變量的名字幾乎能夠包含任何字符,包括Unicode字符:

1 let π = 3.14159
2 let 你好 = "你好世界"
3 let 🐶🐮 = "dogcow"

但不能包含空格、數學符號、箭頭、私用(或無效)的Unicode代碼、繪圖符號或製表符。也不能以數字開頭。

一旦成功聲明一個變量或常量,就不能再更改它的類型。

注:若是你須要使用與Swift保留關鍵字相同的名稱做爲常量或者變量名,你可使用反引號(`)將關鍵字包圍的方式將其做爲名字使用。固然,你應當避免使用關鍵字做爲常量或變量名,除非你真的別無選擇。

四、打印

1 print(friendlyWelcome)
2 // prints "Bonjour!"

用print(_:separator:terminator:)這個方法來打印常量或變量。這是一個能夠打印一個或多個值的全局函數,separator和terminator有默認的值,使用的時候能夠省略。默認狀況下,打印輸出的內容會在最後換行。若是不想換行,能夠將空的字符串傳遞給terminator,例如:

1 print(someValue, terminator: "")

Swift用字符串插入將常量或變量名做爲佔位符,來打印出複雜的信息。

1 print("The current value of friendlyWelcome is \(friendlyWelcome)")
2 // prints "The current value of friendlyWelcome is Bonjour!"

2、註釋

單行註釋:

1 // this is a comment

多行註釋:

1 /* this is also a comment,
2 but written over multiple lines */

不一樣於C語言,Swift中的多行註釋能夠嵌套:

1 /* this is the start of the first multiline comment
2     /* this is the second, nested multiline comment */
3 this is the end of the first multiline comment */

3、分號

1 let cat = "🐱"; print(cat)
2 // prints "🐱"

Swift不須要在每一句表達式後面加分號,可是若是同一行有多個表達式,則須要分號來分隔。

4、整型

一、範圍

 能夠經過min或max屬性來訪問每一種整型數據的最小值或最大值。

1 let minValue = UInt8.min  // minValue is equal to 0, and is of type UInt8
2 let maxValue = UInt8.max  // maxValue is equal to 255, and is of type UInt8

二、Int和UInt

大多數狀況下,你沒必要使用指定長度的整型變量。使用Int便可。固然,也能夠用無符號的UInt。

在32位系統中,Int至關於Int32,UInt至關於UInt32。

在64位系統中,Int至關於Int64,UInt至關於UInt64。

注意:儘可能不要使用UInt,除非你真的須要存儲一個和當前平臺原生字長相同的無符號整數。除了這種狀況,最好使用Int,即便你要存儲的值已知是非負的。統一使用Int可提升代碼的可複用性,避免不一樣整型數據之間的轉換,而且匹配整型的類型推測。

5、浮點型

Double表示64位的浮點數

Float表示32位的浮點數

類型推斷時,浮點數默認被推斷爲Double類型。

Double類型有至少15個小數位的精確度,而Float類型則有6個小數爲的精確度。

6、類型安全和類型推斷

 Swift是一種類型安全的語言,若是聲明變量或常量時沒有指定類型,則Swift會根據值推斷出變量或常量的類型。

1 let meaningOfLife = 42
2 // meaningOfLife is inferred to be of type Int
3 let pi = 3.14159
4 // pi is inferred to be of type Double
5 let anotherPi = 3 + 0.14159
6 // anotherPi is also inferred to be of type Double

7、數值型字面量

十進制沒有前綴,二進制前綴爲0b,八進制前綴爲0o,十六進制前綴爲0x。

1 let decimalInteger = 17
2 let binaryInteger = 0b10001       // 17 in binary notation
3 let octalInteger = 0o21           // 17 in octal notation
4 let hexadecimalInteger = 0x11     // 17 in hexadecimal notation

浮點數能夠是十進制或者十六進制。

十進制的浮點數以大寫或小寫的e來指定指數,基數爲10. 

1.25e2 means 1.25 x 102, or 125.0.

1.25e-2 means 1.25 x 10-2, or 0.0125.

十六進制的浮點數以大寫或小寫的p來指定指數,基數爲2。

0xFp2 means 15 x 22, or 60.0.

0xFp-2 means 15 x 2-2, or 3.75.

下面的浮點字面值都等於十進制的12.1875

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

數值型字面值能夠加上多餘的0和下劃線_來增長數字的可讀性。

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

8、數值型類型轉換

一般狀況下只用默認的整型Int,只有在一些特殊的狀況下才使用其餘整型,好比處理來自外部的指定長度的數據、或者爲了性能或內存佔用或其餘必要的優化。使用顯式指定長度的類型能夠及時發現值溢出而且能夠暗示正在處理特殊數據。

一、整型之間的轉換

不一樣整數類型的變量和常量能夠存儲不一樣範圍的數字,若是存儲的數字超出了該類型的範圍,編譯時就會報錯。

let cannotBeNegative: UInt8 = -1
// UInt8 cannot store negative numbers, and so this will report an error
let tooBig: Int8 = Int8.max + 1
// Int8 cannot store a number larger than its maximum value,
// and so this will also report an error

必須根據不一樣狀況選擇性使用數值型類型轉換,這種選擇性的方式,能夠預防隱式轉換的錯誤並讓你的代碼中的類型轉換意圖變得清晰。

要將一種數字類型轉換成另外一種,你要用當前值來初始化一個指望類型的新數字,這個數字的類型就是你的目標類型。以下,用one的值來初始化一個UInt16的整型,並將其與twoThousand相加。

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

SomeType(ofInitialValue)是一個調用 Swift 構造器並傳入一個初始值的默認方法。在語言內部,UInt16有一個構造器,能夠接受一個UInt8類型的值,因此這個構造器能夠用現有的UInt8來建立一個新的UInt16。注意,你並不能傳入任意類型的值,只能傳入UInt16內部有對應構造器的值。不過你能夠擴展示有的類型來讓它能夠接收其餘類型的值(包括自定義類型)

二、整型和浮點之間的轉換

整型轉浮點數:

1 let three = 3
2 let pointOneFourOneFiveNine = 0.14159
3 let pi = Double(three) + pointOneFourOneFiveNine
4 // pi equals 3.14159, and is inferred to be of type Double

浮點數轉整型:

1 let integerPi = Int(pi)
2 // integerPi equals 3, and is inferred to be of type Int

當用這種方式來初始化一個新的整數值時,浮點值會被截斷。也就是說4.75會變成4,-3.9會變成-3。

注意:結合數字類常量和變量不一樣於結合數字類字面量。字面量3能夠直接和字面量0.14159相加,由於數字字面量自己沒有明確的類型。它們的類型只在編譯器須要求值的時候被推測。

9、類型別名

 當你想要給現有類型起一個更有意義的名字時,類型別名很是有用。例如正在處理特定長度的外部資源的數據:

1 typealias AudioSample = UInt16
2 var maxAmplitudeFound = AudioSample.min
3 // maxAmplitudeFound is now 0

10、布爾型

1 let orangesAreOrange = true
2 let turnipsAreDelicious = false
3 if turnipsAreDelicious {
4     print("Mmm, tasty turnips!")
5 } else {
6     print("Eww, turnips are horrible.")
7 }
8 // prints "Eww, turnips are horrible."

若是你在須要使用Bool類型的地方使用了非布爾值,Swift 的類型安全機制會報錯:

1 let i = 1
2 if i {
3     // this example will compile successfully
4 }

這樣纔是合法的:

1 let i = 1
2 if i == 1 {
3     // this example will compile successfully
4 }

11、元組

元組(tuples)把多個值組合成一個複合值。元組內的值能夠是任意類型,並不要求是相同類型,能夠把任意順序的類型組合成一個元組。

1 let http404Error = (404, "Not Found")
2 // http404Error is of type (Int, String), and equals (404, "Not Found")

(404, "Not Found")元組把一個Int值和一個String值組合起來表示 HTTP 狀態碼的兩個部分:一個數字和一我的類可讀的描述。

元組內容分解:

1 let (statusCode, statusMessage) = http404Error
2 print("The status code is \(statusCode)")
3 // prints "The status code is 404"
4 print("The status message is \(statusMessage)")
5 // prints "The status message is Not Found"

能夠用下劃線忽略某些元素的值:

1 let (justTheStatusCode, _) = http404Error
2 print("The status code is \(justTheStatusCode)")
3 // prints "The status code is 404"

還能夠經過下標來訪問單個元素:

1 print("The status code is \(http404Error.0)")
2 // prints "The status code is 404"
3 print("The status message is \(http404Error.1)")
4 // prints "The status message is Not Found"

能夠在聲明元組時給各個元素命名:

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

給元素命名後,能夠經過元素名來訪問元素的值:

1 print("The status code is \(http200Status.statusCode)")
2 // prints "The status code is 200"
3 print("The status message is \(http200Status.description)")
4 // prints "The status message is OK"

 元組做爲函數的返回值時,很是有用。

注意:元組在臨時組織值的時候頗有用,可是並不適合建立複雜的數據結構。若是你的數據結構並非臨時使用,請使用類或者結構體而不是元組。

 十二:可選型

一、可選

使用可選(optionals)來處理值可能缺失的狀況。

一個可選值是指:有值,值爲x,或者沒有值。

注意:C 和 Objective-C 中並無可選這個概念。最接近的是 Objective-C 中的一個特性,一個方法要不返回一個對象要不返回nil,nil表示「缺乏一個合法的對象」。然而,這隻對對象起做用——對於結構體,基本的 C 類型或者枚舉類型不起做用。對於這些類型,Objective-C 方法通常會返回一個特殊值(好比NSNotFound)來暗示值缺失。這種方法假設方法的調用者知道並記得對特殊值進行判斷。然而,Swift 的可選可讓你暗示任意類型的值缺失,並不須要一個特殊值。

1 let possibleNumber = "123"
2 let convertedNumber = Int(possibleNumber)
3 // convertedNumber is inferred to be of type "Int?", or "optional Int"

上例中,Int初始化器可能失敗,由於字符串可能不能轉化爲數字,因此convertedNumber被推斷爲Int?型,它可能有一個Int值,也可能沒有值。

二、nil

能夠經過賦值nil使可選值變成沒有值的狀態:

1 var serverResponseCode: Int? = 404
2 // serverResponseCode contains an actual Int value of 404
3 serverResponseCode = nil
4 // serverResponseCode now contains no value

注意:nil不能賦給不可選的常量或變量,若是變量的值存在沒有值的狀況,那就將其聲明爲可選型。

若是沒有賦初值,則可選型默認初值爲nil。

1 var surveyAnswer: String?
2 // surveyAnswer is automatically set to nil

注意:Swift的nil不一樣於Objective-C的nil。在Objective-C中,nil是一個不存在的對象的指針。在Swift中,nil不是一個指針,它是某種類型的缺失值,不僅是對象,任意類型的可選值均可以賦值爲nil。

三、if 語句以及強制解包

 可使用if語句來判斷一個可選是否包含值

1 if convertedNumber != nil {
2     print("convertedNumber contains some integer value.")
3 }
4 // prints "convertedNumber contains some integer value."

若是肯定可選包確實含值,你能夠在可選的名字後面加一個感嘆號(!)來獲取值。這個驚歎號表示「我知道這個可選有值,請使用它。」這被稱爲可選值的強制解析(forced unwrapping):

1 if convertedNumber != nil {
2     print("convertedNumber has an integer value of \(convertedNumber!).")
3 }
4 // prints "convertedNumber has an integer value of 123."

注意:使用!來獲取一個不存在的可選值會致使運行時錯誤。使用!來強制解析值以前,必定要肯定可選包含一個非nil的值。

四、可選綁定

使用可選綁定(optional binding)來判斷可選是否有值,若是有,就把值賦給一個臨時常量或者變量。可選綁定能夠用在if和while語句中來對可選的值進行判斷並把值賦給一個常量或者變量。

1 if let actualNumber = Int(possibleNumber) {
2     print("\'\(possibleNumber)\' has an integer value of \(actualNumber)")
3 } else {
4     print("\'\(possibleNumber)\' could not be converted to an integer")
5 }
6 // prints "'123' has an integer value of 123"

「若是Int(possibleNumber)返回的可選Int包含一個值,建立一個叫作actualNumber的新常量並將可選包含的值賦給它。」

能夠在可選綁定中使用常量和變量。若是你想在if語句的第一個分支中操做actualNumber的值,你能夠改爲if var actualNumber,這樣可選包含的值就會被賦給一個變量。

也能夠在一個if語句中包含多個可選綁定,並用where字句來檢查判斷條件的布爾值:

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

五、隱式解析可選

有時候在程序架構中,第一次被賦值以後,能夠肯定一個可選總會有值。在這種狀況下,每次都要判斷和解析可選值是很是低效的,由於能夠肯定它總會有值。

這種類型的可選被定義爲隱式解析可選(implicitly unwrapped optionals)。把想要用做可選的類型的後面的問號(String?)改爲感嘆號(String!)來聲明一個隱式解析可選。

一個隱式解析可選其實就是一個普通的可選,可是能夠被當作非可選來使用,並不須要每次都使用解析來獲取可選值。

let possibleString: String? = "An optional string."
let forcedString: String = possibleString! // requires an exclamation mark
 
let assumedString: String! = "An implicitly unwrapped optional string."
let implicitString: String = assumedString // no need for an exclamation mark

能夠把隱式解析可選當作一個能夠自動解析的可選。只是聲明的時候把感嘆號放到類型的結尾,而不是每次取值的可選名字的結尾。

注意:若是在隱式解析可選沒有值的時候嘗試取值,會觸發運行時錯誤。和在沒有值的普通可選後面加一個驚歎號同樣。

能夠把隱式解析可選當作普通可選來判斷它是否包含值,

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

也能夠在可選綁定中使用隱式解析可選來檢查並解析它的值。

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

注意:若是一個變量以後可能變成nil的話請不要使用隱式解析可選。若是你須要在變量的生命週期中判斷是不是nil的話,請使用普通可選類型。

十3、錯誤處理

使用錯誤處理來響應程序運行中可能發生錯誤的狀況。

與可選相比,可選能夠用它的值是否存在來表示函數運行成功或失敗,而錯誤處理則使得你能夠判斷形成失敗的緣由,必要時,能夠將錯誤傳給程序的其餘部分來處理。

當函數運行失敗,它拋出一個錯誤。函數的調用者則能夠獲取這個錯誤並進行響應:

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

Swift自動將錯誤拋出當前範圍,除非在這裏被catch語句處理。

1 do {
2     try canThrowAnError()
3     // no error was thrown
4 } catch {
5     // an error was thrown
6 }

容許錯誤傳遞給多個catch語句:

 1 func makeASandwich() throws {
 2     // ...
 3 }
 4  
 5 do {
 6     try makeASandwich()
 7     eatASandwich()
 8 } catch Error.OutOfCleanDishes {
 9     washDishes()
10 } catch Error.MissingIngredients(let ingredients) {
11     buyGroceries(ingredients)
12 }

十4、斷言

可選可讓你判斷值是否存在,你能夠在代碼中優雅地處理值缺失的狀況。然而,在某些狀況下,若是值缺失或者值並不知足特定的條件,你的代碼可能並不須要繼續執行。這時,你能夠在你的代碼中觸發一個斷言(assertion)來結束代碼運行並經過調試來找到值缺失的緣由。

一、用斷言進行調試

斷言會在運行時判斷一個邏輯條件是否爲true。從字面意思來講,斷言「斷言」一個條件是否爲真。你可使用斷言來保證在運行其餘代碼以前,某些重要的條件已經被知足。若是條件判斷爲true,代碼運行會繼續進行;若是條件判斷爲false,代碼運行中止,你的應用被終止。

可使用全局assert函數來寫一個斷言。向assert函數傳入一個結果爲true或者false的表達式以及一條信息,當表達式爲false的時候這條信息會被顯示:

1 let age = -3
2 assert(age >= 0, "A person's age cannot be less than zero")
3 // this causes the assertion to trigger, because age is not >= 0

斷言中的信息也能夠省略:

assert(age >= 0)

注意:當你的代碼使用最優編譯時,斷言是無效的,例如使用XCode的默認Release版原本構建app時。

二、何時使用斷言

當條件可能爲假時使用斷言,可是最終必定要保證條件爲真,這樣你的代碼才能繼續運行。斷言的適用情景: 

- 整數的附屬腳本索引被傳入一個自定義附屬腳本實現,可是下標索引值可能過小或者太大。

- 須要給函數傳入一個值,可是非法的值可能致使函數不能正常執行。

- 一個可選值如今是nil,可是後面的代碼運行須要一個非nil值。

注意:斷言可能致使應用終止運行,因此應當仔細設計你的代碼來讓非法條件不會出現。固然,在你的應用發佈以前,有時候非法條件可能出現,這時使用斷言能夠快速發現問題。

相關文章
相關標籤/搜索