# ***Swift基本語法***
- ==參考用書:iOS14 程式設計實戰 by朱克剛==
## 變數與常數宣告
> Swift語言有大小寫之分
```swift
var number = 10
var num1 = 10, num2 = 20
let pi = 3.14
```
- var 宣告的變數可以再修改內容
- let 宣告的變數不能修改
<br>
```swift
var number: Int = 10
let pi: Double = 3.14
let name: String = "Wilson"
```
- 初始化時可以明確地指出資料型態
<br>
### 命名規則
- var, let盡量不要使用
- 名稱不可以是阿拉伯數字開頭
- 1person, 10dollors
- 名稱不可以有空白
- school bus
- 不可以使用特殊符號(+ - * / ...),但底線是可以的
- 第一個字建議小寫
- 可以使用非英文命名
<br>
## 輸出與輸入
### 輸出
```swift
var str = "hello"
print(str)
//hello
```
- 使用print()來顯示
- print()輸出結尾會換行
<br>
```swift
var str = "John"
print("Hi, \(str)")
```
- 可以在字串中插入變數或常數
- 語法為 \\()
<br>
```swift
let str = "hello"
print(str + ",world")
//hello,world
print(str,",world")
//hello ,world
```
- 可以使用+或,來合併兩字串
- +不會在兩字串內加入空白
- 使用 \\() 來合併字串比較好,才不會遇到型態不一致的問題
<br>
```swift
print("Today ", terminator: "")
print("is a good day")
//Today is a good day
print("hello", terminator: ",")
print("world")
//hello,world
```
- print()輸出會換行
- 不希望換行的話在print()函數中補上terminator = "",有點像python的end = ""
- terminator = "xxx" 可以讓結尾是自己想要的格式
<br>
### 輸入
>須建立macOS的Command Line tool
```swift
var name: String?
name = readLine()
```
- readLine()是標準輸入函數
- readLine()對於App開發者並不重要,App的資料輸入是透過專門的元件<br>readLine()只有終端機程式開發者才會經常使用
### 註解
```swift
//註解
/*
多行
註解
*/
```
- //為單行註解
- /* */為多行註解
<br>
## 基本資料型態
>Swift中所有的資料型態都是大寫開頭
### 整數 Int
- 有號整數
- Int, Int8, Int16, Int32, Int64
- 無號整數
- UInt, UInt8, Unt16, UInt32, UInt64
- 數字代表用了多少bit來儲存,Int8表示用了8個bit
- 32位元作業系統 = Int32,64位元作業系統 = Int64
<br>
```swift
print(Int64.max)
//9223372036854775807
print(Int64.min)
//-9223372036854775808
```
- 使用max與min來取得每個數字型態範圍
<br>
```swift
let bin: Int = 0b00000111//2進位
let oct: Int = 0o10//8進位
let hex: Int = 0xA//16進位
```
- 2進位 開頭加0b
- 8進位 開頭加0o
- 16進位 開頭加0x
<br>
```swift
let n = Int.random(in: 3...50)
```
- 上面程式碼會得到範圍為3~50的整數亂數
<br>
### 浮點數 Float, Double
- 有Float,Float32,Float64,Float80 與 Double
- Float = Float32,使用32bit來儲存。Float64 = Double,使用64bit來儲存
- 浮點數沒有min與max屬性
<br>
```swift
var n = 6.9
print(n.rounded())
//7
```
- rounded() 用來將小數第一位做4捨5入
- rounded() 沒有提供留下幾位小數。如要留下小數3位,需要先乘上1000,四捨五入後在除1000
<br>
```swift
var n = 6.0009
print(n.rounded(.up))
//7.0
print(n.rounded(.down))
//6.0
```
- .up 為無條件進位
- .down 為無條件捨去
<br>
### 布林 Bool
- 只有true, false可以放進此型態的變數或常數中
<br>
```swift
var flag = true
flag = !flag
// flag == false
```
- ! 代表not的意思,所以!true 就是flase
<br>
### 字串 String
- 字串需要用雙引號包圍
<br>
```swift
print("嗨\n你好")
//嗨
//你好
```
- \n = 換行,\t = TAB,\\\ = 輸出一個 \
<br>
```swift
let str = """
第一行
第二行
第三行
"""
```
- 連續三個雙引號表示多行字串
<br>
```swift
let a = "abc"
let b = "def"
let c = a + b
print(c)
//c == "abcdef"
```
- 用 + 合併兩字串
<br>
### 二位元 Data
- Data 可以儲存包含文字型態與非文字型態的資料
- 文字形資料指的是String形態中的資料,這些資料沒有文字編碼
- ex. mp3, mov
- 用文字編輯器開啟這些檔案所看到的資料會看一堆亂碼,屬於二位元資料binary data
- Data型態應用
- 藍芽資料傳輸
- 網路資料傳輸
- 各種影像,聲音資料
<br>
### 查看資料屬於何種資料型態
```swift
let n = 20
print(type(of: n))
// "Int"
let str = "hello"
print(type(of: str))
// "String"
```
- 使用type(of:)函數來查看所屬資料型態
<br>
### 型態轉換
- Swift在編譯前會檢查型態,通過才會開始編譯
- a and b 都是整數型態,但Int跟Int64式兩種不同的形態
- 不同的型態的資料不能放在一起運算
<br>
```swift
let n = 10
let str = String(n)
```
- 整數轉字串
<br>
```swift
let str = "30"
let n = Int(str)
```
- 字串轉整數
<br>
```swift
let n = 30
let f = Double(n)
```
- 整數轉浮點數
<br>
```swift
let f = 6.9
let n = Int(f)
// n == 6
```
- 浮點數轉整數
- 相當於去掉小數
<br>
```swift
let b = Bool(trincating: 1)
// b == true
let b = Bool(trincating: 0.3)
// b == true
let b = Bool(trincating: 0)
// b == false
let b = Bool(trincating: "true")
// b == true
```
- 非0數字可以轉換為true
- 數字0轉換為false
<br>
### Tuple
- 用小括號將兩個以上的資料組合放在一起的一種組合型資料型態
<br>
```swift
var size: (Int, Int) = (1,2)
var size = (1,2)
```
- 上面程式碼的 (Int, Int) 代表tuple,包含兩個Int的資料型態
- (Int, Int) 可省略,如第二行程式碼
<br>
```swift
size = (600, 900)
size.0 = 6
size.1 = 9
```
- 第一個值位於tuple索引值0的位置,第二個位於1的位置
- 要修改tuple中的內容可以透過索引值或是用一個新的tuple蓋過去
<br>
```swift
var size: (width: Int, height Int)
size.width = 64
size.height = 81
```
- 可以為tuple中的各部分設定標籤名稱
- 存取個別元素可以透過標籤名稱存取
<br>
```swift
var size: (width: Int, height Int)
size = (64, 81)
var (w, h) = size
// w == 64, h == 81
var (w,_) = size
// w == 64
```
- 也可以宣告數量一致的變數或常數來快速取出tuple中的值
- 不需要的可以用_代替,所以只有將1放入w中
- " _ " 是一個萬用字元,有dont care的意思
<br>
### Optional 型態
- Optimal是Swift中特殊的資料型態,代表現有每種型態能否儲存nil這個值
- nil代表空的意思,相當於C語言中的NULL
- 如果一個變數或常數可能收到nil,該變數或常數的資料型態必須宣告為Optimal型態
- Optimal不是獨立的資料型態,必須和現有資料型態一起使用,因為任何資料型態都可能遇到nil
<br>
```swift
var x: Int?
x = nil
var size: (Int?, Int?)?
size = nil
size = (nil, 10)
size = (10, nil)
size = (nil, nil)
```
- Optimal型態就是在現有形態後方加上 ?
- 任何資料型態都可以加上 ? 形成Optimal型態,包含tuple
<br>
```swift
var y: Int? = 10
let z = y
print(z)
// print "Optimal(10)"
```
- z = y,z取得的是不是10,而是整個y的形式
- 印出z時會得到Optimal(10)而不是單純的10,印出y也是一樣
<br>
```swift
var y: Int? = 10
let z = y!
print(z)
// 10
```
- 要取得原本資料型態的值(內容),需要在變數或常數後方加上!,這樣編譯器就知道我們是單純取值
<br>
```swift
if y == nil{
//y的內容為nil
}else{
//y的內容不為nil
}
```
- 加上 ! 之前一定要確認原本值(內容)是不是nil,如果原本存的是nil,再加上!會導致錯誤
- 可以用條件判斷式來檢測
<br>
```swift
var str: String = "abc"
let n = Int(str) ?? 0
// n== 0
```
- Optimal型態可以使用??來設定當值為nil的預設值
- 上面程式碼因為"abc"無法轉成數字,因此Int(str)會回傳nil,而如果回傳nil就會以0取代存入n
- 這時n的資料型態是Int,不是Int?
<br>
```swift
var x: Int?
x = x! + 1
```
- 第一行變數x因為沒有給nil以外的值,所以x的內容為nil
- 假設要將x+1,需要在非nil的情況下才可以進行,所以要先將x給一個非nil值
- 在x後面加上!取非nil的部分
- ? 改為 ! 時,稱為隱性解開
<br>
```swift
var x: Int!
x = 10
x = x+1
```
- 在一開始就將驚嘆號放在資料型態後方,這樣Swift會自動幫我們取出x中非nil的值
- 一開始就隱性解開的意思
- 隱性解開優點:
- 讓我們同時保有變數可以儲存nil的能力
- 隱性解開缺點:
- 不容易看出變數是Optimal
- 可能會導致忘記檢查nil
- 建議不要使用隱性解開除非很有把握
<br>
## 流程控制
### For-In迴圈
```swift
for 常數 in Sequence{
//code
}
```
- Sequence 是一種協定,符合這個協定的有:
- 陣列
- 字典
- 字串
- 範圍運算子
<br>
```swift
let zoo = ["lion","tiger","elephant","snake"]
for animal in zoo{
print("(animal)\ in the zoo")
}
//lion in the zoo
//tiger in the zoo
//elephant in the zoo
//snake in the zoo
```
- zoo中有四個元素,所以這個迴圈會執行4次
<br>
```swift
for c in "hello"{
print(c)
}
//h
//e
//l
//l
//o
```
- 也可以根據字串內容來決定重複次數,並取得字串中的每一個字元
<br>
```swift
for i in 0...3{
print(i)
}
//0
//1
//2
//3
for i in 0..<3{
print(i)
}
//0
//1
//2
```
- 可以根據數字範圍使用範圍運算子
- n...m代表由n到m包含m
- n.\.<m代表由n到m-1
<br>
### stride函數
```swift
for i in stride(from: 4, to: 1, by: -1){
print(i)
}
//4
//3
//2
```
- stride(from:to:by)
- from 從多少開始
- to 到多少
- 每次進行的參數,除了是整數,也可以是浮點數
<br>
```swift
let array = Array(stride(from: 4, to: 1, by: -1))
print(array)
// [4,3,2]
```
- 可以像上面程式碼一樣,傳入一個陣列
<br>
```swift
for _ in 1...3{
//要重複3次的程式碼
}
```
- for後方的常數如果使用底線 _ ,代表我們只在乎這個迴圈執行了幾次
<br>
### While迴圈
```swift
while 判斷式{
//要重複的程式碼
}
```
- 透過一開始的判斷式來決定是否要重複執行while區段中的程式碼
- 適合使用於程式碼不知道需要重複的場合
<br>
```swift
var n = 0
while n < 5{
print(n)
n += 1
}
//0
//1
//2
//3
//4
```
- 範例
<br>
```swift
while true{
//需要重複的程式碼
}
```
- 用true做出無窮迴圈,在特定情況下才需使用
<br>
### repeat迴圈
```swift
repeat{
//要重複的程式碼
}while 判斷式
```
- 跟while迴圈非常類似
- 差別在於repeat會讓迴圈內的程式碼至少執行一次
<br>
### If...else...
```swift
if 判斷式{
//code
}else if 判斷式{
//code
}else{
//code
}
```
- 只有在判斷式成立時才執行裡面的程式碼
<br>
### 比較運算子
- ==
- a==10
- a的內容等於10回傳true
- \>
- a > 10
- a的內容大於10回傳true
- \<
- a < 10
- a的內容小於10回傳true
- \>=
- a >= 10
- a的內容大於等於10回傳true
- \<=
- a <= 10
- a的內容小於等於10回傳true
- \!=
- a != 10
- a的內容不等於10回傳true
<br>
### 邏輯運算子
且 &&
| A | B | A&&B |
| :----:| :----: | :----: |
| true | true | true |
| true | false | false |
| false | true | false |
| false | false | false |
- &&可以用逗點 , 取代
或 ||
| A | B | A\|\|B |
| :----:| :----: | :----: |
| true | true | true |
| true | false | true |
| false | true | true |
| false | false | false|
否 !
| A | !A |
| :----:| :----: |
| true | false |
| false| true |
<br>
### Switch...Case
- switch語句適合用來判斷數值中的各種不同狀態
```swift
var score = 80
switch score >= 60{
case true:
print("pass")
case false:
print("failed")
}
```
- 依據switch後面變數,常數的運算結果,撰寫不同的case來處理各種不同情況下要做的事
- tuple格式也可以
<br>
```swift
var aqi: Int = 80
switch aqi{
case 0...50:
print("very nice")
case 51...100:
print("nice")
case 101...150:
print("normal")
case 151...200:
print("bad")
default:
print("unknown")
}
```
- 使用default區段來處理case沒有處理完的東西
- 可以使用範圍運算子 ... 來標定範圍
<br>
```swift
var name = Earth
switch name{
case "Sun":
print("star")
case "Earth", "Uranus", "Venus":
print("planet")
case "other":
break
}
```
- 可以將多個case合併
- case區段中如果沒有程式碼,必須加上break
<br>
### Break and continue
- 在迴圈中都可以使用break, continue來改變迴圈行為
- For-in, while, repeat都可使用
- break
- 在迴圈中遇到break會立刻離開迴圈
- continue
- continue 會立刻停止這一次的執行並回到迴圈的判斷處