哈囉,我們又見面了,上個月我們完成了 初學後端 的系列文章,這次我們開始了新的奇幻冒險旅程,要來 iOS
的世界殺怪練等了 !
最一開始,要先熟悉的就是程式語言的 語法,有點像是你進入到一個新的遊戲世界之後,你最先要做的,就是去知道遊戲世界的人在講些什麼,聽懂、看懂他們說的話之後,才能跟 NPC 說話、解任務。
用 var
宣告可變的變數,用 let
宣告不可變的常數。
// 變數,這點跟 Kotlin 是一樣的
var justme = "我是 RS 唷~"
// 常數,不可變
// 在 Kotlin 是使用 `val constant = "我不可以被變更"`
let constant = "我不可以被變更"
// 也可以用 顯式(Explicit) 直接講明變數的型別
let name : String = "RS"
var age : Int = 25
// 跨型別輸出的串接,可以用加號 `+`,但要自己轉字串
// 也可以用 `\(variable)` 來串接
print(name + "'s age is " + String(age))
print("After ten years, " + name + "'s age is \(age + 10)")
/*
輸出為
RS's age is 25
After ten years, RS's age is 35
*/
在 Swift 的世界中,可以用
\(variable)
安插變數在字串裡,
和Python
的$(variable)
概念相似
print("int max: \(Int.max) to min: \(Int.min)")
/* 輸出為
* int min: -9223372036854775808 to max: 9223372036854775807
*/
print(pow(2, 63))
/* 輸出為
* 9223372036854775808
*/
print(9223372036854775808)
/*
* Overflow Error
*/
// 可以觀察出,Int 的最大值是 2 的 63 次方 - 1
其他 primitives 的範圍,就交給大家自己去找出來了。
// if else,比較可惜的是還沒支援範圍運算符號(range operator)
// 也就是以下的寫法是 `錯` 的
if statusCode in 200...208 || statusCode == 226{
...
}
// 以下是 `正確` 的
if (200...208).contains(statusCode) || statusCode == 226 {
print("Good, \(statusCode) \(status), get \(payload)")
}else if(400...429).contains(statusCode) || statusCode == 431 || statusCode == 451 {
print("Bad, \(statusCode) \(status), get \(payload)")
}else {
print("I don't know others, \(statusCode) \(status), get \(payload)")
}
// 如此一來,我就包含了 200~208、226 的範圍
// 覺得總有一天,會改成比較直覺的方式的~
// -----------------------------------------------
// switch case,預設不用寫 break,
// 需要繼續執行到下一個 case 的話,
// 就加 `callthrough` 關鍵字。
// 如果是判斷 tuple 的話,可以變得很彈性
func testSwitch(data: (statusCode: Int, status: String, payload: Array<Int>)) {
let statusCode = data.statusCode
let status = data.status
let payload = data.payload
switch data {
case (200, "OK", _): // `_`底線,代表的是那個欄位不限制值
print("Good, \(statusCode) \(status), get \(payload)")
case (404, "NotFound", _):
print("Bad, \(statusCode) \(status), get \(payload)")
default:
print("不能理解")
}
}
// 執行看看
testSwitch(data: (200, "OK", [9527, 9487, 9453, 5201314]))
/* 輸出為
* Good, 200 OK, get [9527, 9487, 9453, 5201314]
*/
先不要怕什麼是 tuple
,等等就會提到了,它是其中一種資料而已。
Swift
的if else
和Kotlin
的if else
很像,差在條件句可以不用括號,要括號也是可以,和Python
的if else
概念一樣,Python
可括號、也可不括號
Swift
的switch case
就保留了Java
式的switch case
,而且不用寫break
關鍵字,相比之下,Python
拿掉了switch case
、Kotlin
改用when
,從這點可以感覺到Swift
身上,還看得到一點點舊式語言的影子,同時又改掉不方便的部分
攝影師:JESHOOTS.com,連結:Pexels
熟悉了 基本語法,還要再搭配 資料結構 才行,如果你覺得一次看這麼多太吃力,可以先在這裡休息一下,把上面的基礎語法練熟,在 Xcode
的 Playground
自己多試試不同的組合,再進行到資料結構的階段。
Array
)在 Swift
沒有 List
,但 Swift
的 Array
的概念,就是跟 Python
的 List
和 Java
、Kotlin
的 ArrayList
很像。因為這個資料結構最常使用,所以特別講多一點。
Array
?// 一般的純 Int array
var intArray = [9, 5, 2, 7]
print(intArray)
/* 輸出為
* [9, 5, 2, 7]
*/
// 如果要在 array 裡放入多型別
// 則必須 顯式 宣告你的陣列
var anyArray: [Any] = [0, 100, 3.14159, "Hi"]
print(anyArray)
/* 輸出為
* [0, 100, 3.14159, "Hi"]
*/
// 如果是要創建空 Array 的話,不能直接用空的中括號
//var emptyArray = [] // Error
// 需要 顯式 宣告 Array,有三種顯示宣告方式
var firstArrayCreationMethod = [Int]()
var secondArrayCreationMethod: [String] = []
var thirdArrayCreationMethod: Array<String> = []
在
Swift
的Array
中,值得注意的是創建空Array
的方法,其中三種都可以,知道有這三種方法之後,就可以挑一個自己喜歡的方法,來作為固定使用
Array
內的值 ?// 範圍取值,拿 index 1~3
print(anyArray[1...3])
/* 輸出為
* [100, 3.14159, "Hi"]
*/
// 想知道 array 的長度
// 在 Python 是 len(anyArray)
// 在 Kotlin 是 anyArray.size
print(anyArray.count)
/* 輸出為
* 4
*/
// 從 0 到 anyArray 的長度-1
// `..<` 對右邊的數值 是 `不包含`
print(anyArray[0..<anyArray.count])
/* 輸出為
* [0, 100, 3.14159, "Hi"]
*/
// 從 0 到 anyArray 的長度-1
// `...` 對右邊的數值是 `包含`
print(anyArray[0...anyArray.count-1])
/* 輸出為
* [0, 100, 3.14159, "Hi"]
*/
// 單邊的也可以
print(anyArray[0...])
/* 輸出為
* [0, 100, 3.14159, "Hi"]
*/
在 Swift 的範圍運算符號(range operator),是使用
...
、..<
來進行有包含/沒包含的範圍取值
Array
內的值 ?// 增,可以在 array 裡面,再加入一個 array
anyArray.append([10, 9, 8])
print(anyArray)
/* 輸出為
* [0, 100, 3.14159, "Hi", [10, 9, 8]]
*/
// 但如果要從 anyArray 拿出裡面的 Array 的話
// 拿出來的 array 會是 Any 型別
// 取用之後還要強制轉型回 Array,非常麻煩
print((anyArray[4] as! [Int])[0])
/* 輸出為
* 10
*/
// 也可以針對 index 來插入
anyArray.insert("插入!", at: 2)
print(anyArray)
/* 輸出為
* [0, 100, "插入!", 3.14159, "Hi", [10, 9, 8]]
*/
// 改,把 array 第一個值從 0 改成 字串
// (注意:因為我的 array 是 Any 型別才可以這樣做)
anyArray[0] = "嘿嘿看我改你"
print(anyArray)
/* 輸出為
* ["嘿嘿看我改你", 100, "插入!", 3.14159, "Hi", [10, 9, 8]]
*/
// 刪,針對某個 index 移除 array
anyArray.remove(at: 1)
print(anyArray)
/* 輸出為
* ["嘿嘿看我改你", "插入!", 3.14159, "Hi", [10, 9, 8]]
*/
在
Swift
的array
操作,用insert
插入值、用remove
移除值,修改值就直接用=
改值
適合用來存放一些雜亂、臨時產生的數值
// Tuple 是用小括號包住 (跟 Python 的 Tuple 一樣)
let tuple = ("這是", "iOS系列文章", "tuple還可包含多型別的變數哦", 9527, [94.87, 94, 87])
print(tuple)
/* 輸出為
* ("這是", "iOS系列文章", "tuple還可包含多型別的變數哦", 9527, [94.87, 94.0, 87.0])
*/
// 顯式 宣告 tuple,會讓拿資料時更直覺
let explicitTuple: (statusCode: Int, status: String, payload: [Int]) = (200, "OK", [1,2,3,4,5])
print("GET \(explicitTuple.statusCode) \(explicitTuple.status): \(explicitTuple.payload)")
/* 輸出為
* GET 200 OK: [1, 2, 3, 4, 5]
*/
Swift
的Tuple
,和Kotlin
的Pair
、Python
的Tuple
概念相似
適合用來放有對應性的資料
// Dictionary 也是用中括號包住
// 值得注意的是,Key 只能用同一種型別
// Value 也是同一種型別
// 而 Key 和 Value 可以不同型別
let dictionary = [200: "OK", 404: "NotFound"]
print(dictionary)
/* 輸出為
* [200: "OK", 404: "NotFound"]
*/
// 增
dic[500] = "InternalServerError"
print(dic)
/* 輸出為
* [200: "OK", 404: "Error", 500: "InternalServerError"]
*/
// 刪,有兩種方法
dic[200] = nil
print(dic)
/* 輸出為
* [404: "Error", 500: "InternalServerError"]
*/
dic.removeValue(forKey: 404)
print(dic)
/* 輸出為
* [500: "InternalServerError"]
*/
Swift
的Dictionary
用起來的感覺,和Python
的dict
很像,但差別是在Python
的dict
是 大括號,而Swift
是 中括號
適合用來放不要重複且順序不重要的資料
// 用中括號包起來
// 需要 顯式 宣告,不然會變成 array
// (Python 的 Set 是用大括號包起來)
var set: Set = [9527, 9527, 9453, 5201314]
print(set)
/* 輸出為
* [9527, 5201314, 9453]
*/
set.insert(12345)
set.remove(9453)
print(set)
/* 輸出為
* [9527, 5201314, 12345]
*/
Swift
的Set
,需要標明是Set
型別(顯式),insert
和remove
則用起來跟上面幾個很像
這次把 基本語法 和 資料結構 放在同一篇,是因為我等不及要趕快進入到下一個階段了,所以略過了一些在 Python篇 有提到的細節,像是怎麼宣告 primitive(Int
, Float
, Double
, String
等等)、各個 primitive 的範圍、primitive 之間的轉型之類的議題,我打算邊實作邊學,不在一開始就挖太深,可能之後有看到什麼,覺得值得紀錄的,再回來充實這篇文章。
到目前為止,接觸 iOS
算是已經三天左右,還是被一堆術語跟語法搞混,像是我剛剛才發現,原來 「Swift
的 Protocol
就是 Java/Kotlin
的 Interface
」,還有「為什麼 Swift
同時保留了 Struct
和 Class
?」、「Swift
的 Closure
跟 Java/Kotlin
的 Lambda
差在哪 ?」等等的問號瘋狂冒出來,要一件一件是去釐清,真的是挺累的,不過就是需要走過這條路,才能把各程式語言之間的隔閡抹平,才不會各說各話,我說的術語你聽不懂、你說的術語我也聽不懂,造成溝通上的阻礙。
我是 RS,這是我的 不做怎麼知道系列 文章,我們 下次見。