Swift編程高級教程

常量與變量

 

常量和變量是某個特定類型的值的名字,若是在程序運行時值不能被修改的是一個常量,反之是一個變量。 數組

常量和變量的聲明

Swift中的常量和變量在使用前必須先聲明。其中let關鍵字聲明常量,var關鍵字聲明變量: app

//聲明一個名爲maximumNumberOfLoginAttempts的整型常量,而且值爲10 let maximumNumberOfLoginAttempts = 10 //聲明一個名爲currentLoginAttempt的整型變量,而且值爲0 var currentLoginAttempt = 0

能夠在同一行聲明多個變量,中間用逗號,隔開: ide

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

提示
若是在程序運行的時候值不須要發生改變,應該將它們聲明爲常量,不然聲明爲變量 函數

變量的值能夠進行修改: oop

var friendlyWelcome = "Hello!" friendlyWelcome = "Bonjour!" //friendlyWelcome的值發生改變

常量的值一旦設置後就不能在修改: this

let languageName = "Swift" languageName = "Swift++" //編譯時出錯

類型說明

在Swift中聲明常量或者變量能夠在後面用冒號:指定它們的數據類型。 編碼

//聲明一個String類型的變量,能夠存放String類型的值 var welcomeMessage: String

提示
實際應用中不多須要指定變量數據類型,Swift會根據所設置的值的類型進行推導。 spa

命名規則

Swift中可使用任意字符給常量和變量命名,包括Unicode編碼,好比中文、Emoji等: .net

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

名字裏面不能包含數學運算符、箭頭、非法的Unicode字符以及不能識別的字符等,而且不能以數字開頭。同一個做用域的變量或者常量不能同名。 code

提示
若是想用關鍵字做爲變量的名字,要用(`)包裹起來。爲了方便理解,若是不是萬不得已,不該該使用關鍵字做爲變量的名字。

打印變量的值

println函數能夠打印常量或者變量的值:

println("The current value of friendlyWelcome is \(friendlyWelcome)") //打印「The current value of friendlyWelcome is Bonjour!」

註釋

註釋是用來幫助理解和記憶代碼功能的,並不會參與編譯。Swift有兩種註釋形式,單行註釋和多行註釋:

//這是單行註釋,用兩個斜線開頭,直到改行的結尾 /*這是多行註釋, 能夠橫跨不少行, /*比C語言更加NB的是,*/ 它居然還支持嵌套的註釋!*/

分號

Swift中語句結尾的分號;不是必須的,不過若是想要在同一行中寫多個語句,則須要使用;進行分隔。


簡化setter的聲明

若是沒有爲計算屬性的setter的新值指定名字,則默認使用newValue。下面是Rect結構體的另一種寫法:

struct Cuboid { var width = 0.0, height = 0.0, depth = 0.0 var volume: Double { return width * height * depth } } let fourByFiveByTwo = Cuboid(width: 4.0, height: 5.0, depth: 2.0) println("the volume of fourByFiveByTwo is \(fourByFiveByTwo.volume)") //打印「the volume of fourByFiveByTwo is 40.0」 

屬性觀察者

屬性觀察者用來觀察和響應屬性值的變化。每次設置屬性的值都會調用相應的觀察者,哪怕是設置相同的值。

能夠給除延時存儲屬性之外的任何存儲屬性添加觀察者。經過重寫屬性,能夠在子類中給父類的屬性(包括存儲屬性和計算屬性)添加觀察者。

提示
不須要給類自己定義的計算屬性添加觀察者,徹底能夠在計算屬性的setter中完成對值的觀察。

經過下面兩個方法對屬性進行觀察:

  • willSet在屬性的值發生改變以前調用。
  • didSet在設置完屬性的值後調用。

若是沒有給willSet指定參數的話,編譯器默認提供一個newValue作爲參數。一樣,在didSet中若是沒有提供參數的話,默認爲oldValue。

提示
willSet和didSet觀察者在屬性進行初始化的時候不會被調用。

struct SomeStructure { static var storedTypeProperty = "Some value." static var computedTypeProperty: Int { //return an Int value here } } enum SomeEnumeration { static var storedTypeProperty = "Some value." static var computedTypeProperty: Int { //return an Int value here } } class SomeClass { class var computedTypeProperty: Int { //return an Int value here } } 

提示
上面的計算屬性都是隻讀的,但實際上能夠定義爲可讀可寫

使用類型屬性

類型屬性經過類型名字和點操做符進行訪問和設置,而不是經過實例對象:

println(SomeClass.computedTypeProperty) //print "42" println(SomeStructure.storedTypeProperty) //prints "Some value" SomeStructure.storedTypeProperty = "Another value." println(SomeStructure.storedTypeProperty) //prints "Another value." 

下面演示瞭如何使用一個結構體來對聲道音量進行建模,其中每一個聲道音量範圍爲0-10。
staticPropertiesVUMeter_2x

var shoppingList: String[] = ["Eggs", "Milk"] // 把shoppingList初始化爲兩個初始數據元素

這個shoppingList變量經過String[]形式被聲明爲一個String類型值的數組,由於這個特定的數組被指定了值類型String,因此咱們只能用這個數組類存儲String值,這裏咱們存儲了兩個字面常量String值(「Eggs」和「Milk」)。

提示
這個shoppingList是聲明爲變量(var說明符)而不是聲明爲常量(let說明符),由於後面的例子裏將有更多的元素被加入這個數組.

這裏,這個字面常量數組只包含了2個String值,他能匹配shoppingList數組的類型聲明,因此能夠用他來給shoppingList變量賦值初始化。
得益於Swift的類型推斷機制,咱們在用數組字面常量來初始化一個數組時不須要明確指定他的類型,用以下這個很方便的方式:

println("Tht shopping list contains \(shoppingList.count) items.") // prints "The shopping list contains 2 items."

數組有一個叫作isEmpty的屬性來表示該數組是否爲空,即count屬性等於 0:

shoppingList += "Baking Powder" //shoppingList now contains 4 items

咱們還有能夠直接給一個數組加上另外一個類型一致的數組:

shoppingList.insert("Maple Syrup", atIndex: 0) // shoppingList now contains 7 items // "Maple Syrup" is now the first item in the list

當咱們須要在數組的某個地方移除一個既有元素的時候,能夠調用數組的方法removeAtIndex,該方法的返回值是被移除掉的元素;

let mapleSyrup = shoppingList.removeAtIndex(0) // the item that was at index 0 has just been removed // shoppingList now contains 6 items, and no Maple Syrup // the mapleSyrup constant is now equal to the removed "Maple Syrup" string

當特殊狀況咱們須要移除數組的最後一個元素的時候,咱們應該避免使用removeAtIndex方法,而直接使用簡便方法removeLast來直接移除數組的最後一個元素,removeLast方法也是返回被移除的元素。

let apples = shoppingList.removeLast() // the last item in the array has just been removed // shoppingList now contains 5 items, and no cheese // the apples constant is now equal to the removed "Apples" string

數組元素的遍歷

在Swift語言裏,咱們能夠用快速枚舉(for-in)的方式來遍歷整個數組的元素:

for (index, value) in enumerate(shoppingList) { println("Item \(index + 1): \(value)")
} // Item 1: Six eggs // Item 2: Milk // Item 3: Flour // Item 4: Baking Powder // Item 5: Bananas

數組建立與初始化

咱們能夠用以下的語法來初始化一個肯定類型的空的數組(沒有設置任何初始值):

var someInts = Int[]() println("someInts is of type Int[] with \(someInts.count) items.") // prints "someInts is of type Int[] with 0 items.

變量someInts的類型會被推斷爲Int[],由於他被賦值爲一個Int[]類型的初始化方法的結果。
若是程序的上下文已經提供了其類型信息,好比一個函數的參數,已經申明瞭類型的變量或者常量,這樣你能夠用一個空數組的字面常量去給其賦值一個空的數組(這樣寫[]):

someInts.append(3) // someInts now contains 1 value of type Int someInts = [] // someInts is now an empty array, but is still of type Int[]

Swift的數組一樣也提供了一個建立指定大小並指定元素默認值的初始化方法,咱們只需給初始化方法的參數傳遞元素個數(count)以及對應默認類型值(repeatedValue):

var anotherThreeDoubles = Array(count: 3, repeatedValue: 2.5) // anotherThreeDoubles is inferred as Double[], and equals [2.5, 2.5, 2.5]

最後,咱們數組也能夠像字符串那樣,能夠把兩個已有的類型一致的數組相加獲得一個新的數組,新數組的類型由兩個相加的數組的類型推斷而來:

for index in 1...5 { println("\(index) times 5 is \(index * 5)")
} // 1 times 5 is 5 // 2 times 5 is 10 // 3 times 5 is 15 // 4 times 5 is 20 // 5 times 5 is 25

提示
index常量的做用域只在循環體裏面。若是須要在外面使用它的值,則應該在循環體外面定義一個遍歷。

若是不須要從範圍中獲取值的話,可使用下劃線_代替常量index的名字,從而忽略這個常量的值:

let base = 3 let power = 10 var answer = 1 for _ in 1...power {
    answer *= base
} println("\(base) to the power of \(power) is \(answer)") //prints "3 to the power of 10 is 59049"

下面是使用for-in遍歷數組裏的元素:

let numberOfLegs = ["spider": 8, "ant": 6, "cat": 4] for (animalName, legCount) in numberOfLegs { println("\(animalName)s have \(legCount) legs")
} //spiders have 8 legs //ants have 6 legs //cats have 4 legs

因爲字典是無序的,所以迭代的順序不必定和插入順序相同。

對於字符串String進行遍歷的時候,獲得的是裏面的字符Character:

for var index = 0; index < 3; ++index { println("index is \(index)")
} //index is 0 //index is 1 //index is 2

下面是這種循環的通用格式,for循環中的分號不能省略:
for 初始化; 循環條件; 遞增變量 {
循環體語句
}
這些語句的執行順序以下:

  1. 第一次進入是先執行初始化表達式,給循環中用到的常量和變量賦值。
  2. 執行循環條件表達式,若是爲false,循環結束,不然執行花括號{}裏的循環體語句。
  3. 循環體執行完後,遞增遍歷表達式執行,而後再回到上面的第2條。

這中形式的for循環能夠用下面的while循環等價替換:

初始化
while 循環條件 {
    循環體語句
    遞增變量
}

在初始化是聲明的常量或變量的做用域爲for循環裏面,若是須要在循環結束後使用index的值,須要在for循環以前進行聲明:

while 循環條件 {
    循環體語句
}

 

do-while循環

 

do-while循環的通用格式:

 

temperatureInFahrenheit = 40 if temperatureInFahrenheit <= 32 { println("It's very cold. Consider wearing a scarf.")
} else { println("It's not that cold. Wear a t-shirt.")
} //prints "It's not that cold. Wear a t-shirt."

若是須要增長更多的判斷條件,能夠將多個if-else語句連接起來:

temperatureInFahrenheit = 72 if temperatureInFahrenheit <= 32 { println("It's very cold. Consider wearing a scarf.")
} else if temperatureInFahrenheit >= 86 { println("It's really warm. Don't forget to wear sunscreen.")
}

switch語句

switch語句能夠將同一個值與多個判斷條件進行比較,找出合適的代碼進行執行。最簡單的形式是將一個值與多個同類型的值進行比較:

let somePoint = (1, 1) switch somePoint { case (0, 0): println("(0, 0) is at the origin") case (_, 0): println("(\(somePoint.0), 0) is on the x-axis") case (0, _): println("(0, \(somePoint.1)) is on the y-axis") case (-2...2, -2...2): println("(\(somePoint.0), \(somePoint.1)) is inside the box") default: println("(\(somePoint.0), \(somePoint.1)) is outside of the box")
} // prints "(1, 1) is inside the box"

coordinateGraphSimple_2x

Swift中case表示的範圍能夠是重疊的,可是會匹配最早發現的值。

值的綁定

switch可以將值綁定到臨時的常量或變量上,而後在case中使用,被稱爲value binding。

let yetAnotherPoint = (1, -1) switch yetAnotherPoint { case let (x, y) where x == y: println("(\(x), \(y)) is on the line x == y") case let (x, y) where x == -y: println("(\(x), \(y)) is on the line x == -y") case let (x, y): println("(\(x), \(y)) is just some arbitrary point")
} // prints "(1, -1) is on the line x == -y"

coordinateGraphComplex_2x


流程控制-跳轉語句

流程轉換語句(跳轉語句)能夠改變代碼的執行流程。Swift包含下面四種跳轉語句:

  • continue
  • break
  • fallthrough
  • return

下面會對continue、break和fallthrough進行講解,而return表達式將在函數中進行介紹。

continue表達式

continue語句能夠提早結束一次循環,之間調到第二次循環開始,可是並不會終止循環。

提示
在for-condition-increment類型的循環中,自增語句在continue後仍然會執行。

下面的例子會刪除字符串中的元音字符和空格:

let numberSymbol: Character = "三" // Simplified Chinese for the number 3 var possibleIntegerValue: Int? switch numberSymbol { case "1", "١", "一", "๑":
    possibleIntegerValue = 1 case "2", "٢", "二", "๒":
    possibleIntegerValue = 2 case "3", "٣", "三", "๓":
    possibleIntegerValue = 3 case "4", "٤", "四", "๔":
    possibleIntegerValue = 4 default: break } if let integerValue = possibleIntegerValue { println("The integer value of \(numberSymbol) is \(integerValue).")
} else { println("An integer value could not be found for \(numberSymbol).")
} // prints "The integer value of 三 is 3."

fallthrough語句

Swift的switch語句中不能在一個case執行完後繼續執行另一個case,這遇C語言中的狀況不同。若是你須要實現相似於C語言中switch的行爲,可使用fallthrough關鍵字。

let integerToDescribe = 5 var description = "The number \(integerToDescribe) is" switch integerToDescribe { case 2, 3, 5, 7, 11, 13, 17, 19:
    description += " a prime number, and also" fallthrough default:
    description += " an integer." } println(description) // prints "The number 5 is a prime number, and also an integer."

提示
fallthrough語句執行後,switch不會再去檢查下面的case的值。

標號語句

在循環或者switch語句中使用break只能跳出最內層,若是有多個循環語句嵌套的話,須要使用標號語句才能一次性跳出這些循環。
標號語句的基本寫法爲:

<code class="go hljs" style="font-weight: bold; color: #6e6b5e;" data-origin="" <pre><code="" while="" 條件語句="" {"="">標號名稱: while 條件語句 {
    循環體
}

下面是標號語句的一個例子:

let finalSquare = 25 var board = Int[](count: finalSquare + 1, repeatedValue: 0)
board[03] = +08; board[06] = +11; board[09] = +09; board[10] = +02 board[14] = -10; board[19] = -11; board[22] = -02; board[24] = -08 var square = 0 var diceRoll = 0 gameLoop: while square != finalSquare { if ++diceRoll == 7 { diceRoll = 1 } switch square + diceRoll { case finalSquare: // diceRoll will move us to the final square, so the game is over break gameLoop case let newSquare where newSquare > finalSquare: // diceRoll will move us beyond the final square, so roll again continue gameLoop default: // this is a valid move, so find out its effect square += diceRoll
        square += board[square]
    }
} println("Game over!")

break或continue執行後,會跳轉到標號語句處執行,其中break會終止循環,而continue則終止當前此次循環的執行。


blog.diveinedu.net

相關文章
相關標籤/搜索