iT邦幫忙

1

[不做怎麼知道系列之Android開發者偷學iOS的奇幻冒險 Day2] - 解新手主線任務 #耐住性子不越級打怪 #Swift #基礎語法

Sam 2020-03-23 13:26:53538 瀏覽

https://ithelp.ithome.com.tw/upload/images/20200323/20124548twI607Ye59.png

哈囉,我們又見面了,上個月我們完成了 初學後端 的系列文章,這次我們開始了新的奇幻冒險旅程,要來 iOS 的世界殺怪練等了 !

1. 基礎使用

最一開始,要先熟悉的就是程式語言的 語法,有點像是你進入到一個新的遊戲世界之後,你最先要做的,就是去知道遊戲世界的人在講些什麼,聽懂、看懂他們說的話之後,才能跟 NPC 說話、解任務。

1.1 宣告變數 (Variable Declaration)

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) 概念相似

1.2 變數範圍

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 的範圍,就交給大家自己去找出來了。

1.3 流程控制

// 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,等等就會提到了,它是其中一種資料而已。

Swiftif elseKotlinif else 很像,差在條件句可以不用括號,要括號也是可以,和 Pythonif else 概念一樣,Python 可括號、也可不括號

Swiftswitch case 就保留了 Java 式的 switch case,而且不用寫 break 關鍵字,相比之下,Python 拿掉了 switch caseKotlin 改用 when,從這點可以感覺到 Swift 身上,還看得到一點點舊式語言的影子,同時又改掉不方便的部分

https://images.pexels.com/photos/442576/pexels-photo-442576.jpeg?cs=srgb&dl=ps4-442576.jpg&fm=jpg

攝影師:JESHOOTS.com,連結:Pexels


2. 資料結構

熟悉了 基本語法,還要再搭配 資料結構 才行,如果你覺得一次看這麼多太吃力,可以先在這裡休息一下,把上面的基礎語法練熟,在 XcodePlayground 自己多試試不同的組合,再進行到資料結構的階段。

2.1 陣列 (Array)

Swift 沒有 List,但 SwiftArray 的概念,就是跟 PythonListJavaKotlinArrayList 很像。因為這個資料結構最常使用,所以特別講多一點。

怎麼創建 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> = []

SwiftArray 中,值得注意的是創建空 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]]
 */

Swiftarray 操作,用 insert 插入值、用 remove 移除值,修改值就直接用 = 改值

2.2 Tuple

適合用來存放一些雜亂、臨時產生的數值

// 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]
 */

SwiftTuple,和 KotlinPairPythonTuple 概念相似

2.3 Dictionary

適合用來放有對應性的資料

// 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"]
 */

SwiftDictionary 用起來的感覺,和 Pythondict 很像,但差別是在 Pythondict 是 大括號,而 Swift 是 中括號

2.4 Set

適合用來放不要重複且順序不重要的資料

// 用中括號包起來
// 需要 顯式 宣告,不然會變成 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]
 */

SwiftSet,需要標明是 Set 型別(顯式),insertremove 則用起來跟上面幾個很像

3. 總結

這次把 基本語法 和 資料結構 放在同一篇,是因為我等不及要趕快進入到下一個階段了,所以略過了一些在 Python篇 有提到的細節,像是怎麼宣告 primitive(Int, Float, Double, String 等等)、各個 primitive 的範圍、primitive 之間的轉型之類的議題,我打算邊實作邊學,不在一開始就挖太深,可能之後有看到什麼,覺得值得紀錄的,再回來充實這篇文章。

到目前為止,接觸 iOS 算是已經三天左右,還是被一堆術語跟語法搞混,像是我剛剛才發現,原來 「SwiftProtocol 就是 Java/KotlinInterface」,還有「為什麼 Swift 同時保留了 StructClass ?」、「SwiftClosureJava/KotlinLambda 差在哪 ?」等等的問號瘋狂冒出來,要一件一件是去釐清,真的是挺累的,不過就是需要走過這條路,才能把各程式語言之間的隔閡抹平,才不會各說各話,我說的術語你聽不懂、你說的術語我也聽不懂,造成溝通上的阻礙。

我是 RS,這是我的 不做怎麼知道系列 文章,我們 下次見。



尚未有邦友留言

立即登入留言