Swift 的基本概念
raywenderlich-Programming in Swfit:Fundamentals 筆記
這篇主要記錄一些重要的觀念,在了解這些觀念之後就能夠清楚的知道程式碼運行的方式,這樣就能提升寫程式的能力,也能讓寫出來的程式碼更簡潔有力。
數值的型態轉換
swift 可以使用 Int(“ ”) 將 String 轉換成數值,這邊值得注意的點是因為有可能會填入非數值,所以使用了 optional,這樣一來輸入為非數值時的輸出就是 nil 而不是程式出錯。
Tuple
在 swift 中的 tuple 是一個能夠將各種型態的資料用小括號結合在一起的一個列表,tuple 是 value type 而非 reference type。
let airlineTicket: (string, string, int) = ("長榮", "BR102", 150)print(airlineTicket.0)print(airlineTicket.1)print(airlineTicket.2)
上方是 tuple 的一種使用方式,雖然這樣使用能夠顯示出資料,但是卻會造成程式碼混亂的狀況,所以應該給參數名字,如下方。
let airlineTicket: (airline:string, flight:string, flightTime:int) = ("長榮", "BR102", 150)print(airlineTicket.airline)print(airlineTicket.flight)print(airlineTicket.flightTime)
Array
array 與 tuple 之間有一些差異,其中之一是將相同型態的資料儲存在一起,並且使用中括號結合在一起。
let airline:[String] = ["長榮", "ANA", "華航"]print(airline.0)print(airline.1)print(airline.2)
新增資料時,資料會預設增加在最後面,但也可以指定位置。
airline.append("虎航") airline += ["樂桃"] //作用同 .appendairline.insert("星宇",2) //將星宇插在第二個位置,ANA的後方
swift 能夠把 array 複製出來。
let budgetAirlines = Array(airline[3...4])
airline[0…2 ] 代表複製了 0 到 2 的資料,此時的資料型態是 ArraySlice,而不是 array,所以沒辦法像 array 一樣使用 index 來取得資料。
宣告成 ArraySlice 的資料還有一個與 array 不同的點,就是起始 index 的數值並非一定從 0 開始,而是從切下資料的起始位置開始算起,在上方例子的起始位置為 3。
Repeat-while
swift 中並不是使用 do 搭配 while 而是使用 repeat。
For-in
for i in 0...5 { print(i)}
上方為目前 swift 的標準用法,i 會帶入 0 到 5。
for i in 0..<5 where i > 2 { print(i)}
如果想要輸出 0 到 4 ,可以使用 .. < ,並且可以使用 where 來加上條件。
for _ in 0...2 { Int.random(in:0...100)}
如果想要輸出亂數,那麼 i 就無意義,可以使用 _ 將 i 代替。
for (i=0;i<5;i++) { print(i);}
這種 C 語言的用法已經在 swift3 之後被強制淘汰,如果使用的話會出現錯誤。
for i in 0..<5 {
if i == 2 { continue } if i == 3 { break } print(i)}
在 for 迴圈中, 若想要跳過則可以使用 continue,而如果想要執行到某個地方就中斷則可以使用 break。
Dictionary
dictionary 與 array 一樣是用來儲存相同型態的 value,但是每一個 value 都會被一把 unique key 對應, key 的型態不一定會與 value 相同。
var ticket:[String:String] = ["airline":"長榮","flight":"BR102"]print(ticket["airline"])print(ticket["flight"])for (key,value) in ticket { print("\(key): \(value)")}
上方例子 airline 與 flight 就是 key,而對應的長榮與 BR102 就是 value,若想在 dictionary 裡增加資料,可以用 updateValue,或者直接新增也可以。
ticket["from"] = "桃園"ticket.updateValue("福岡", forKey: "to")
若要刪除資料,則是用 removeValue。
ticket.removeValue(forKey: "to")
Set
set 有點像 array,但是如果使用 set 儲存重複的值,在儲存時只會儲存一次,而且在輸出時並不會照著順序輸出。
var color:Set<String> = ["black","blue","white","yellow","yellow"]print(color) // black blue white yellow 順序不一定
這邊使用 Set 列出了一些顏色。
color.remove("blue")
這裡若想要刪掉 blue,可以使用 remove 來刪除。
named type 與 compound type
name type 是在定義時能夠給一個特定的名稱,屬於這種類型的有 class. structure. enumerations. protocols. string. boolean. int… 等等大多數的資料型態。
compound type 則是沒有名字的類別,是定義在 swift 本身中,這種類型的有 tuple 以及 function。
value type 與 reference type
除了上述的分類方法之外,另一種較常見的分類是 value 與 reference 。
value type 是代表每一個實例都會有屬於自己的資料,並不會與其他人分享,這種類型的有 struct. tuple 與 enum。
reference type 則是每個實例共享一份相同的資料,class 就屬於這種類型。
Function
func ticket(airline: String, flight: String , _ something: String){}
這裡的 airline 以及 flight 不屬於 function,因此若不需要使用到名字可以加上 _ 省略,就像上例中的 something 一樣。
Structure
struct ticket { let airline: String var flight: String var flightTime: Int mutating func changeFlight(newFlight: String,newFlightTime: Int){ flight = newFlight
flightTime = newFlightTime }}var myTicket = ticket(airline:"長榮", flight:"BR102", flightTime:150)myTicket.changeFlight(newFlight:"BR106", newFlightTime: 130)
上方為 struct 的用法,要注意的是因為 struct 是屬於 value type,因此原先是不允許更改實例的,若強行更改會出現 Cannot assign to property: ‘self’ is immutable 的錯誤,此時在 function 前面加上 mutating 就能更改。
mutating 代表會將更動指定給一個新的實例,並且新的實例會在方法結束後將舊的實例覆蓋掉。
Class
class ticket { let airline: String var flight: String var flightTime: Int let passportNumber: Int? init(airline:String,flight:String,flightTime: Int,
passportNumber:Int? = nil) { self.airline = airline self.flight = flight self.flightTime = flightTime self.passportNumber = passportNumber } func changeFlight(newFlight: String,newFlightTime: Int){ flight = newFlight flightTime = newFlightTime }}var myTicket = ticket(airline:"長榮", flight:"BR102", flightTime:150)myTicket.changeFlight(newFlight:"BR106", newFlightTime: 130)
這裡將上方的 struct 例子改成 class 的例子,並且加上了 passportNumber。
首先改成 class 之後就會變成 reference type,因此可以把 mutating 刪除。再來 struct 會自動初始化,但是 class 並不會,所以要自行加上 init 來完成初始化,這裡透過參數傳遞來完成初始化。
在初始化時因為 passportNumber 是選填的,所以在初始化時使用 ? 來代表可有可無,並且將其預設為無。