繁體中文 學習
Apple 官方程式語言 Swift

從零開始,掌握 Swift 核心概念、物件導向設計、非同步程式設計,打造屬於你的 iOS / macOS App!

18+
教學章節
60+
程式碼範例
25+
互動測驗
100%
繁體中文
🌱 入門基礎
從最基本的概念開始,循序漸進理解 Swift 語言的核心特性
🍎
Swift 介紹
了解 Swift 的歷史、特性,以及為什麼它是開發 Apple 生態系統 App 的最佳選擇。
入門
📝
語法基礎
學習 Swift 的基本語法,包含 print、註解、型別推斷和字串插值。
入門
📦
變數與常數
了解 varlet 的差異,以及 Swift 的不可變性設計哲學。
入門
🔢
資料型別
認識 Int、Double、Bool、String 等基本型別,並學習型別轉換技巧。
入門
運算子
算術、比較、邏輯、範圍、空合運算子——掌握 Swift 全系列運算工具。
入門
🔤
字串操作
字串插值、多行字串、字元操作、常用字串方法全攻略。
入門
🔄 控制流程 & 集合型別
條件判斷、迴圈與 Swift 強大的集合操作
🔀
條件判斷
if、else if、else 與三元運算子,讓程式根據條件做出不同反應。
入門
🎛️
Switch 語句
Swift 的 switch 功能遠超其他語言,支援模式匹配、範圍與 where 條件。
中階
🔁
迴圈
for-in、while、repeat-while,以及 break、continue 控制迴圈。
入門
📋
陣列 Array
建立、存取、修改陣列,並運用 map、filter、reduce 等高階函式。
中階
📖
字典 Dictionary
鍵值對資料結構,快速查找、增刪改查操作全教學。
中階
🔵
集合 Set
唯一元素集合,支援聯集、交集、差集等數學集合運算。
中階
🏗️ 進階特性
函式、物件導向、協定驅動設計與 Swift 現代特性
⚙️
函式
函式定義、參數標籤、預設值、variadic 與函式型別。
中階
🎯
閉包
理解閉包語法、尾隨閉包、捕獲值與高階函式的優雅使用。
中階
選擇型別
Optional 綁定、guard let、可選鏈與強制解包的安全使用。
中階
🧱
結構體
值型別 vs 參考型別,mutating 方法與計算屬性。
中階
🏛️
類別
繼承、初始化器、deinit、final 修飾符與類別設計最佳實踐。
中階
🤝
協定
Swift 協定導向程式設計,讓程式碼更靈活、更可測試、更易擴充。
進階
🔷
泛型
撰寫可重複使用、類型安全的泛型函式與泛型型別。
進階
🛡️
錯誤處理
throw、try、catch、defer 完整錯誤處理流程。
進階
非同步並發
async/await、Task、Actor,現代化的 Swift 並發程式設計。
進階

🎮 準備好測試你的 Swift 知識了嗎?

完成章節後參加綜合測驗,鞏固你的學習成果!

第一章

Swift 介紹

認識這門由 Apple 打造的現代程式語言,了解它的特色與應用場景。

Swift 6.0

🍎 什麼是 Swift?

Swift 是由 Apple 於 2014 年發佈的現代程式語言,設計目標是取代 Objective-C,提供更安全、更快速、更簡潔的開發體驗。

Swift 是一門靜態型別語言,兼具表達力與效能,特別適合開發:

  • iPhone / iPad App(iOS)
  • Mac App(macOS)
  • Apple Watch App(watchOS)
  • Apple TV App(tvOS)
  • 伺服器端應用程式(Linux / Windows)

🚀 為什麼選擇 Swift?

超快執行速度
Swift 比 Objective-C 快 2.6 倍,比 Python 快 8.4 倍(Apple 官方數據)。
🛡️
安全設計
Optional 型別設計消除空指針問題,強型別系統在編譯期就能抓出錯誤。
✍️
簡潔語法
不需要分號、型別推斷、字串插值,程式碼更像自然語言。
🌐
開源社群
自 2015 年開源,擁有活躍社群,支援多平台開發。

📅 Swift 發展歷程

年份版本重要里程碑
2014Swift 1.0在 WWDC 首次發表,作為 Objective-C 的現代替代品
2015Swift 2.0開放原始碼,支援 Linux 平台
2016Swift 3.0大幅改善 API 命名規範
2017Swift 4.0Codable 協定、改善字串 API
2019Swift 5.0ABI 穩定性,SwiftUI 發佈
2021Swift 5.5async/await 結構化並發
2022Swift 5.7新型別推斷、正規表達式字面量
2024Swift 6.0完整並發安全、嚴格並發檢查

💻 開發環境設置

Mac + Xcode(建議)若要開發 iOS / macOS App,建議使用 Mac 並安裝 Xcode,這是 Apple 官方的整合開發環境,免費提供。
線上練習本教學提供即時程式碼範例,你也可以使用 SwiftFiddle.comReplit 線上執行 Swift 程式碼。

安裝步驟(Mac)

  1. 開啟 Mac App Store
  2. 搜尋並安裝 Xcode(免費,約 12 GB)
  3. 開啟 Xcode,建立新的 Playground 即可開始撰寫 Swift 程式碼

👋 第一個 Swift 程式

按照傳統,我們先來看 Swift 版的 Hello World:

hello.swift
// 這是 Swift 的第一個程式
// 單行註解以 // 開頭

/* 
   多行註解使用 /* */ 包圍
*/

print("Hello, 世界!")
print("歡迎來到 Swift 的世界!")

// Swift 無需分號
let language = "Swift"
let version = 6.0
print("目前使用 \(language) \(version) 版")
▶ 輸出結果
Hello, 世界! 歡迎來到 Swift 的世界! 目前使用 Swift 6.0 版
Swift 與其他語言的不同Swift 不需要在每行末尾加分號 ;,也不需要 main() 入口函式(在腳本模式下)。
第二章

語法基礎

掌握 Swift 的基本語法結構,包含 print、型別推斷、字串插值與函式入門。

🖨️ print() 輸出

Swift 使用 print() 函式輸出資訊到主控台。

print.swift
// 基本 print 用法
print("Hello, Swift!")

// 輸出多個值(預設以空格分隔)
print("年齡:", 25, "歲")

// 自訂分隔符號
print("蘋果", "香蕉", "葡萄", separator: "、")

// 不換行輸出
print("載入中", terminator: "")
print("...")

// 輸出布林值
print(true, false)
▶ 輸出結果
Hello, Swift! 年齡: 25 歲 蘋果、香蕉、葡萄 載入中... true false

💬 字串插值 String Interpolation

使用 \(運算式) 語法在字串中嵌入變數或運算式,這是 Swift 最常用的字串格式化方式。

interpolation.swift
let name = "小明"
let age = 20
let score = 95.5

// 基本字串插值
print("我是 \(name),今年 \(age) 歲")

// 嵌入運算式
print("明年我 \(age + 1) 歲")

// 數學計算
let price = 100
let quantity = 5
print("總金額:\(price * quantity) 元")

// 條件運算式
let isPassed = score >= 60
print("成績:\(score),\(isPassed ? "及格" : "不及格")")
▶ 輸出結果
我是 小明,今年 20 歲 明年我 21 歲 總金額:500 元 成績:95.5,及格

📌 型別推斷 Type Inference

Swift 可以自動推斷變數的型別,但你也可以手動指定型別。

type_inference.swift
// 型別推斷(Swift 自動判斷)
let number = 42          // 推斷為 Int
let pi = 3.14159         // 推斷為 Double
let greeting = "Hello"   // 推斷為 String
let flag = true          // 推斷為 Bool

// 明確型別標注
let temperature: Double = 36
let count: Int = 100
let message: String = "Swift 好棒"

// 使用 type(of:) 查看型別
print(type(of: number))     // Int
print(type(of: pi))         // Double
print(type(of: greeting))   // String
▶ 輸出結果
Int Double String

💡 多行字串

multiline.swift
// 使用三個雙引號建立多行字串
let poem = """
春眠不覺曉,
處處聞啼鳥。
夜來風雨聲,
花落知多少。
"""

let name = "Swift"
let version = 6
let info = """
語言:\(name)
版本:\(version)
公司:Apple Inc.
"""

print(poem)
print("---")
print(info)
▶ 輸出結果
春眠不覺曉, 處處聞啼鳥。 夜來風雨聲, 花落知多少。 --- 語言:Swift 版本:6 公司:Apple Inc.
第三章

變數與常數

理解 varlet 的核心差異,這是 Swift 設計哲學的重要基礎。

📦 var vs let

let — 常數(不可更改)
let birthYear = 2000
let PI = 3.14159
let appName = "MyApp"
// birthYear = 2001 // ❌ 錯誤!
var — 變數(可以更改)
var score = 0
var name = "未命名"
score = 100    // ✅ 可以修改
name = "Swift"  // ✅ 可以修改
最佳實踐盡可能使用 let,只有在需要修改的情況下才用 var。這能讓程式更安全、更容易理解。

🔢 完整範例

variables.swift
// 常數 - 一旦設定就不能更改
let maxScore = 100
let playerName = "英雄聯盟玩家"

// 變數 - 可以修改
var currentScore = 0
var level = 1
var isAlive = true

print("玩家:\(playerName)")
print("目前關卡:\(level) 級")
print("目前分數:\(currentScore) / \(maxScore)")

// 升級
currentScore += 50
level += 1

print("\n升級後:")
print("關卡:\(level) 級")
print("分數:\(currentScore)")

// 多個變數同時宣告
var x = 0, y = 0, z = 0
print("\n座標:(\(x), \(y), \(z))")
▶ 輸出結果
玩家:英雄聯盟玩家 目前關卡:1 級 目前分數:0 / 100 升級後: 關卡:2 級 分數:50 座標:(0, 0, 0)

❓ Optional 選擇型別

Swift 引入 Optional 型別來安全地處理「可能不存在的值」(nil)。

optionals_basic.swift
// 使用 ? 宣告 Optional
var nickname: String? = nil
var age: Int? = 25

print(nickname ?? "沒有暱稱")  // nil 合并运算符
print(age ?? 0)

// 設定值
nickname = "Swift 學習者"
print(nickname!)  // 強制解包(確定有值時才用)

// Optional 綁定(安全解包)
if let validAge = age {
    print("年齡是:\(validAge)")
} else {
    print("年齡未知")
}

// guard let 解包
func greet(name: String?) {
    guard let unwrappedName = name else {
        print("名字不存在")
        return
    }
    print("你好,\(unwrappedName)!")
}

greet(name: "Alice")
greet(name: nil)
▶ 輸出結果
沒有暱稱 25 Swift 學習者 年齡是:25 你好,Alice! 名字不存在
第四章

資料型別

Swift 的型別系統非常嚴格,了解各種型別是寫出安全程式的基礎。

📊 基本資料型別總覽

型別說明範例預設值範圍
Int整數let n: Int = 42-9223372036854775808 ~ 9223372036854775807
Double64位浮點數(精確)let d: Double = 3.14精度約15-16位
Float32位浮點數let f: Float = 3.14精度約6-7位
Bool布林值let b: Bool = truetrue / false
String字串let s = "Hello"Unicode 字元序列
Character單一字元let c: Character = "A"單一 Unicode 字元

🔄 型別轉換

type_conversion.swift
// Swift 不會自動轉換型別,需要明確轉換
let intValue: Int = 42
let doubleValue: Double = Double(intValue)  // Int → Double
let floatValue: Float = Float(intValue)     // Int → Float

print("\(intValue) → Double: \(doubleValue)")
print("\(intValue) → Float: \(floatValue)")

// Double → Int(截斷小數)
let pi = 3.99999
let intPi = Int(pi)  // 3(不四捨五入,直接截斷)
print("π ≈ \(pi) → Int: \(intPi)")

// String ↔ Int
let numStr = "123"
if let num = Int(numStr) {
    print("字串 \"\(numStr)\" 轉換為數字:\(num)")
}

let number = 456
let str = String(number)
print("數字 \(number) 轉換為字串:\"\(str)\"")
▶ 輸出結果
42 → Double: 42.0 42 → Float: 42.0 π ≈ 3.99999 → Int: 3 字串 "123" 轉換為數字:123 數字 456 轉換為字串:"456"

🔢 整數特殊功能

int_features.swift
// 整數最大最小值
print("Int 最大值:\(Int.max)")
print("Int 最小值:\(Int.min)")
print("Int8 範圍:\(Int8.min) ~ \(Int8.max)")

// 不同進位系統
let decimal = 255
let binary = 0b11111111      // 二進位
let octal = 0o377            // 八進位
let hexadecimal = 0xFF       // 十六進位

print("十進位:\(decimal)")
print("二進位:\(binary)")
print("八進位:\(octal)")
print("十六進位:\(hexadecimal)")

// 可讀性下劃線
let oneMillion = 1_000_000
let creditCard = 1234_5678_9012_3456
print("一百萬:\(oneMillion)")
▶ 輸出結果
Int 最大值:9223372036854775807 Int 最小值:-9223372036854775808 Int8 範圍:-128 ~ 127 十進位:255 二進位:255 八進位:255 十六進位:255 一百萬:1000000
第五章

運算子

Swift 提供豐富的運算子,從算術到範圍,幫你簡潔表達程式邏輯。

➕ 算術運算子

arithmetic.swift
let a = 20
let b = 6

print(a + b)   // 26 加法
print(a - b)   // 14 減法
print(a * b)   // 120 乘法
print(a / b)   // 3 整數除法
print(a % b)   // 2 取餘數

// 字串也支援 + 運算
let first = "Hello"
let second = " Swift"
print(first + second)  // Hello Swift

// 複合賦值運算子
var score = 100
score += 50   // score = score + 50
score -= 20   // score = score - 20
score *= 2    // score = score * 2
score /= 3    // score = score / 3
print("分數:\(score)")
▶ 輸出結果
26 14 120 3 2 Hello Swift 分數:86

🔍 比較與邏輯運算子

comparison.swift
// 比較運算子 - 返回 Bool
print(5 == 5)   // true  等於
print(5 != 3)   // true  不等於
print(5 > 3)    // true  大於
print(5 < 10)   // true  小於
print(5 >= 5)   // true  大於等於
print(5 <= 4)   // false 小於等於

// 邏輯運算子
let a = true
let b = false

print(a && b)  // false AND:兩者都要 true
print(a || b)  // true  OR:至少一個 true
print(!a)      // false NOT:取反

// 實際應用
let age = 25
let hasID = true
let canDrink = age >= 18 && hasID
print("可以喝酒:\(canDrink)")
▶ 輸出結果
true true true true true false false true false 可以喝酒:true

📏 範圍運算子 Range Operators

Swift 獨特的範圍運算子,讓迴圈和陣列操作更直觀。

range.swift
// 封閉範圍 a...b (包含 a 和 b)
for i in 1...5 {
    print(i, terminator: " ")
}
print()

// 半開放範圍 a..
▶ 輸出結果
1 2 3 4 5 1 2 3 4 [30, 40, 50] [10, 20, 30] true false

❓ 空合運算子 Nil-Coalescing

nil_coalescing.swift
// ?? 運算子:若左邊為 nil,則使用右邊的預設值
var username: String? = nil
let displayName = username ?? "訪客"
print("歡迎,\(displayName)!")  // 歡迎,訪客!

username = "SwiftLearner"
let displayName2 = username ?? "訪客"
print("歡迎,\(displayName2)!")  // 歡迎,SwiftLearner!

// 三元運算子
let temperature = 35
let weather = temperature > 30 ? "好熱🔥" : "涼爽🌈"
print("天氣:\(weather)")
▶ 輸出結果
歡迎,訪客! 歡迎,SwiftLearner! 天氣:好熱🔥
第六章

字串操作

Swift 的 String 是功能強大的值型別,支援 Unicode、豐富的方法與現代字串操作。

🔤 字串基本操作

strings.swift
var greeting = "Hello, Swift!"

// 基本屬性
print(greeting.count)         // 13 字元數
print(greeting.isEmpty)       // false 是否為空
print(greeting.uppercased())  // 全大寫
print(greeting.lowercased())  // 全小寫

// 包含 / 開頭 / 結尾 檢查
print(greeting.contains("Swift"))      // true
print(greeting.hasPrefix("Hello"))     // true
print(greeting.hasSuffix("!"))         // true

// 字串替換
let newGreeting = greeting.replacingOccurrences(of: "Hello", with: "你好")
print(newGreeting)  // 你好, Swift!

// 分割字串
let csv = "蘋果,香蕉,葡萄,西瓜"
let fruits = csv.split(separator: ",")
print(fruits)  // ["蘋果", "香蕉", "葡萄", "西瓜"]

// 去除空白
let padded = "  Hello  "
print(padded.trimmingCharacters(in: .whitespaces))
▶ 輸出結果
13 false HELLO, SWIFT! hello, swift! true true true 你好, Swift! ["蘋果", "香蕉", "葡萄", "西瓜"] Hello

🌏 Unicode 完整支援

unicode.swift
// Swift 完整支援 Unicode
let emoji = "Swift 🐦 很棒!"
print(emoji)
print("字元數:\(emoji.count)")

// 遍歷每個字元
for char in "SWIFT" {
    print(char, terminator: "-")
}
print()

// 中文字串
let chineseText = "學習程式設計,改變世界"
print(chineseText.count)  // 11

// 字串比較
let str1 = "apple"
let str2 = "apple"
print(str1 == str2)   // true
print(str1 < "banana")  // true (字母順序)
▶ 輸出結果
Swift 🐦 很棒! 字元數:9 S-W-I-F-T- 11 true true
第七章

條件判斷

讓程式根據不同條件執行不同邏輯,這是程式設計的核心能力之一。

🔀 if / else if / else

conditionals.swift
// 基本 if-else
let temperature = 28

if temperature >= 35 {
    print("天氣很熱,注意防曬!")
} else if temperature >= 25 {
    print("天氣溫暖舒適 ☀️")
} else if temperature >= 15 {
    print("天氣有些涼,帶件外套")
} else {
    print("天氣寒冷,多穿點!")
}

// 成績評分系統
let score = 78

let grade: String
if score >= 90 {
    grade = "A(優秀)"
} else if score >= 80 {
    grade = "B(良好)"
} else if score >= 70 {
    grade = "C(普通)"
} else if score >= 60 {
    grade = "D(及格)"
} else {
    grade = "F(不及格)"
}

print("分數:\(score) → 等級:\(grade)")
▶ 輸出結果
天氣溫暖舒適 ☀️ 分數:78 → 等級:C(普通)

🎯 if let — 安全解包

if_let.swift
// if let 同時解包多個 optional(Swift 5.7+)
var firstName: String? = "Tim"
var lastName: String? = "Cook"

if let first = firstName, let last = lastName {
    print("全名:\(first) \(last)")
}

// guard let 早退模式
func processAge(_ ageStr: String) {
    guard let age = Int(ageStr), age >= 0 else {
        print("無效的年齡輸入:\(ageStr)")
        return
    }
    
    if age >= 18 {
        print("年齡 \(age):成年人")
    } else {
        print("年齡 \(age):未成年")
    }
}

processAge("25")
processAge("16")
processAge("abc")
▶ 輸出結果
全名:Tim Cook 年齡 25:成年人 年齡 16:未成年 無效的年齡輸入:abc
第八章

Switch 語句

Swift 的 switch 遠比其他語言強大,支援模式匹配、範圍和多條件,且不需要 break!

🎛️ 基本 Switch

switch_basic.swift
let day = 3

switch day {
case 1:
    print("星期一 💼")
case 2:
    print("星期二")
case 3:
    print("星期三")
case 4, 5:                    // 多個值共用
    print("星期四或五 🎉")
case 6, 7:
    print("週末!😎")
default:
    print("無效日期")
}

// 範圍匹配
let score = 85
switch score {
case 90...100:
    print("優秀 🏆")
case 80..<90:
    print("良好 ⭐")
case 70..<80:
    print("普通")
case 60..<70:
    print("及格")
default:
    print("不及格 😢")
}
▶ 輸出結果
星期三 良好 ⭐

🔮 進階模式匹配

switch_advanced.swift
// 元組匹配
let point = (2, 0)

switch point {
case (0, 0):
    print("原點")
case (_, 0):
    print("X 軸上,x = \(point.0)")
case (0, _):
    print("Y 軸上,y = \(point.1)")
case (-2...2, -2...2):
    print("在中央區域")
default:
    print("其他位置")
}

// where 條件
let number = 42
switch number {
case let n where n < 0:
    print("\(n) 是負數")
case let n where n % 2 == 0:
    print("\(n) 是偶數")
case let n where n % 2 != 0:
    print("\(n) 是奇數")
default:
    break
}
▶ 輸出結果
X 軸上,x = 2 42 是偶數
第九章

迴圈

for-in、while、repeat-while 三種迴圈各有適用場景,靈活運用讓程式簡潔有力。

🔁 for-in 迴圈

for_in.swift
// 數字範圍
print("=== 1到5 ===")
for i in 1...5 {
    print(i, terminator: " ")
}
print()

// 遍歷陣列
let planets = ["水星", "金星", "地球", "火星"]
for planet in planets {
    print("行星:\(planet)")
}

// 帶索引遍歷
for (index, planet) in planets.enumerated() {
    print("\(index + 1). \(planet)")
}

// stride - 自訂步長
print("\n偶數:", terminator: "")
for i in stride(from: 0, to: 11, by: 2) {
    print(i, terminator: " ")
}

print("\n倒數:", terminator: "")
for i in stride(from: 10, through: 0, by: -2) {
    print(i, terminator: " ")
}
▶ 輸出結果
=== 1到5 === 1 2 3 4 5 行星:水星 行星:金星 行星:地球 行星:火星 1. 水星 2. 金星 3. 地球 4. 火星 偶數:0 2 4 6 8 10 倒數:10 8 6 4 2 0

⏰ while / repeat-while

while.swift
// while - 先判斷再執行
var countdown = 5
print("發射倒計時:")
while countdown > 0 {
    print("\(countdown)...")
    countdown -= 1
}
print("🚀 發射!")

// repeat-while - 至少執行一次(類似 do-while)
var password = ""
var attempts = 0
repeat {
    attempts += 1
    password = attempts == 3 ? "swift123" : "wrong"
    print("第 \(attempts) 次嘗試")
} while password != "swift123"
print("✅ 登入成功!")

// break 和 continue
print("\n跳過 3 的倍數:", terminator: "")
for i in 1...10 {
    if i % 3 == 0 { continue }  // 跳過
    print(i, terminator: " ")
}
▶ 輸出結果
發射倒計時: 5... 4... 3... 2... 1... 🚀 發射! 第 1 次嘗試 第 2 次嘗試 第 3 次嘗試 ✅ 登入成功! 跳過 3 的倍數:1 2 4 5 7 8 10
第十章

陣列 Array

陣列是有序的元素集合,Swift 提供強大的高階函式讓操作更優雅。

📋 建立與操作陣列

arrays.swift
// 建立陣列
var fruits = ["蘋果", "香蕉", "葡萄"]
var numbers: [Int] = [1, 2, 3, 4, 5]
var emptyArray: [String] = []

// 存取元素
print(fruits[0])          // 蘋果
print(fruits.first!)      // 蘋果
print(fruits.last!)       // 葡萄
print(fruits.count)       // 3

// 修改陣列
fruits.append("西瓜")              // 加到末尾
fruits.insert("草莓", at: 1)       // 插入特定位置
fruits.remove(at: 0)               // 刪除索引 0
fruits[0] = "鳳梨"                 // 修改元素

print(fruits)

// 常用屬性
print("是否為空:\(fruits.isEmpty)")
print("包含西瓜:\(fruits.contains("西瓜"))")
▶ 輸出結果
蘋果 蘋果 葡萄 3 ["鳳梨", "草莓", "葡萄", "西瓜"] 是否為空:false 包含西瓜:true

⚡ 高階函式 map / filter / reduce

higher_order.swift
let scores = [45, 82, 61, 93, 55, 78, 88]

// map - 轉換每個元素
let doubled = scores.map { $0 * 2 }
print("加倍:\(doubled)")

// filter - 過濾元素
let passing = scores.filter { $0 >= 60 }
print("及格的:\(passing)")

// reduce - 聚合計算
let total = scores.reduce(0) { $0 + $1 }
let average = Double(total) / Double(scores.count)
print("總分:\(total)")
print("平均:\(String(format: "%.1f", average))")

// sorted
let sorted = scores.sorted()
let sortedDesc = scores.sorted(by: >)
print("升序:\(sorted)")
print("降序:\(sortedDesc)")

// 鏈式操作:過濾及格成績,轉為等級
let grades = scores
    .filter { $0 >= 60 }
    .map { score -> String in
        switch score {
        case 90...100: return "A"
        case 80..<90: return "B"
        case 70..<80: return "C"
        default: return "D"
        }
    }
print("等級:\(grades)")
▶ 輸出結果
加倍:[90, 164, 122, 186, 110, 156, 176] 及格的:[82, 61, 93, 78, 88] 總分:502 平均:71.7 升序:[45, 55, 61, 78, 82, 88, 93] 降序:[93, 88, 82, 78, 61, 55, 45] 等級:["B", "D", "A", "C", "B"]
第十三章

函式 Function

函式是 Swift 的核心概念,支援靈活的參數標籤、預設值、可變參數與多返回值。

⚙️ 函式基本語法

functions.swift
// 基本函式
func greet(name: String) -> String {
    return "你好,\(name)!"
}
print(greet(name: "小明"))

// 多個參數
func add(_ a: Int, _ b: Int) -> Int {
    return a + b
}
print(add(3, 5))

// 預設參數值
func createProfile(name: String, age: Int = 18, role: String = "用戶") -> String {
    return "\(name)(\(age)歲)- \(role)"
}
print(createProfile(name: "Alice"))
print(createProfile(name: "Bob", age: 25, role: "管理員"))

// 回傳多個值(使用元組)
func minMax(_ array: [Int]) -> (min: Int, max: Int) {
    return (array.min()!, array.max()!)
}
let result = minMax([5, 3, 8, 1, 9, 2])
print("最小:\(result.min),最大:\(result.max)")

// 可變參數
func sum(_ numbers: Int...) -> Int {
    return numbers.reduce(0, +)
}
print(sum(1, 2, 3, 4, 5))
▶ 輸出結果
你好,小明! 8 Alice(18歲)- 用戶 Bob(25歲)- 管理員 最小:1,最大:9 15

🏷️ 參數標籤

param_labels.swift
// 外部標籤 內部標籤: 型別
func move(from startPoint: String, to endPoint: String) {
    print("從 \(startPoint) 移動到 \(endPoint)")
}
// 呼叫時使用外部標籤
move(from: "台北", to: "高雄")

// 使用 _ 省略外部標籤
func multiply(_ x: Int, by y: Int) -> Int {
    return x * y
}
print(multiply(6, by: 7))

// @discardableResult - 可以忽略回傳值
@discardableResult
func saveToDatabase(data: String) -> Bool {
    print("儲存:\(data)")
    return true
}
saveToDatabase(data: "用戶資料")
▶ 輸出結果
從 台北 移動到 高雄 42 儲存:用戶資料
第十四章

閉包 Closure

閉包是自包含的程式碼區塊,可以捕獲環境中的值,是 Swift 函數式程式設計的核心。

🎯 閉包語法演進

closures.swift
// 完整閉包語法
let fullClosure = { (x: Int, y: Int) -> Int in
    return x + y
}

// 省略型別(推斷)
let shortClosure = { (x: Int, y: Int) in x + y }

// 使用 $0, $1 簡寫參數
let minimal = { $0 + $1 }

print(fullClosure(3, 4))    // 7
print(shortClosure(3, 4))   // 7
print(minimal(3, 4))        // 7

// 尾隨閉包(最後一個參數是閉包)
let numbers = [5, 2, 8, 1, 9]

// 標準寫法
let sorted1 = numbers.sorted(by: { (a, b) -> Bool in return a < b })

// 尾隨閉包
let sorted2 = numbers.sorted { $0 < $1 }

print(sorted2)  // [1, 2, 5, 8, 9]

// 實際應用:非同步回調
func fetchData(completion: (String) -> Void) {
    let data = "來自伺服器的資料"
    completion(data)
}

fetchData { data in
    print("收到:\(data)")
}
▶ 輸出結果
7 7 7 [1, 2, 5, 8, 9] 收到:來自伺服器的資料

📸 捕獲值 Capture Values

capture.swift
// 閉包可以捕獲並修改外部變數
func makeCounter() -> () -> Int {
    var count = 0
    return {
        count += 1
        return count
    }
}

let counter1 = makeCounter()
let counter2 = makeCounter()

print(counter1())  // 1
print(counter1())  // 2
print(counter1())  // 3
print(counter2())  // 1(獨立計數器)
print(counter2())  // 2
▶ 輸出結果
1 2 3 1 2
第十六章

結構體 Struct

結構體是 Swift 最重要的型別之一,值型別語意讓程式碼更安全、更可預測。

🧱 定義與使用結構體

structs.swift
struct Player {
    var name: String
    var health: Int
    var level: Int
    
    // 計算屬性
    var isAlive: Bool {
        return health > 0
    }
    
    var description: String {
        return "\(name) (等級\(level), 血量\(health))"
    }
    
    // Mutating 方法(修改 struct 需加 mutating)
    mutating func takeDamage(_ damage: Int) {
        health = max(0, health - damage)
        print("\(name) 受到 \(damage) 點傷害,剩餘血量:\(health)")
    }
    
    mutating func levelUp() {
        level += 1
        health = min(100, health + 20)
        print("\(name) 升級到 \(level) 級!")
    }
}

var hero = Player(name: "英雄", health: 100, level: 1)
print(hero.description)
hero.takeDamage(30)
hero.levelUp()
print("存活中:\(hero.isAlive)")
▶ 輸出結果
英雄 (等級1, 血量100) 英雄 受到 30 點傷害,剩餘血量:70 英雄 升級到 2 級! 存活中:true
第十七章

類別 Class

類別是參考型別,支援繼承與多型,適合代表需要共享狀態的複雜物件。

🏛️ 類別定義與繼承

classes.swift
// 基礎類別
class Animal {
    var name: String
    var sound: String
    
    init(name: String, sound: String) {
        self.name = name
        self.sound = sound
    }
    
    func speak() {
        print("\(name) 說:\(sound)!")
    }
    
    deinit {
        // 物件被銷毀時呼叫
        print("\(name) 離開了")
    }
}

// 繼承
class Dog: Animal {
    var breed: String
    
    init(name: String, breed: String) {
        self.breed = breed
        super.init(name: name, sound: "汪汪")
    }
    
    // 覆寫父類別方法
    override func speak() {
        print("🐕 \(name)(\(breed)):\(sound)!搖尾巴中...")
    }
    
    func fetch() {
        print("\(name) 去撿球了!🎾")
    }
}

let animal = Animal(name: "動物", sound: "...")
let dog = Dog(name: "小黑", breed: "柴犬")

animal.speak()
dog.speak()
dog.fetch()

// 型別檢查
print(dog is Animal)  // true(繼承關係)
print(dog is Dog)     // true
▶ 輸出結果
動物 說:...! 🐕 小黑(柴犬):汪汪!搖尾巴中... 小黑 去撿球了!🎾 true true

⚖️ Class vs Struct

特性Class(類別)Struct(結構體)
型別參考型別 Reference值型別 Value
繼承✅ 支援❌ 不支援
記憶體Heap(堆疊)Stack(棧)
複製行為共享同一個物件複製獨立副本
deinit✅ 支援❌ 不支援
適用場景共享狀態、繼承關係簡單資料模型、值語意
Apple 建議優先使用 struct,只有在需要繼承或共享狀態時才使用 class
進階章節

協定 Protocol

Protocol 是 Swift 的核心設計模式,提供比繼承更靈活的程式碼復用方式。

🤝 定義與實作協定

protocols.swift
// 定義協定
protocol Drawable {
    var color: String { get }
    func draw()
    func area() -> Double
}

protocol Resizable {
    mutating func resize(by factor: Double)
}

// 結構體遵守多個協定
struct Circle: Drawable, Resizable {
    var radius: Double
    var color: String
    
    func draw() {
        print("畫一個 \(color) 的圓形,半徑 \(radius)")
    }
    
    func area() -> Double {
        return Double.pi * radius * radius
    }
    
    mutating func resize(by factor: Double) {
        radius *= factor
    }
}

struct Rectangle: Drawable {
    var width: Double
    var height: Double
    var color: String
    
    func draw() {
        print("畫一個 \(color) 的矩形 \(width) × \(height)")
    }
    
    func area() -> Double {
        return width * height
    }
}

// 協定型別使用
var shapes: [any Drawable] = [
    Circle(radius: 5.0, color: "紅色"),
    Rectangle(width: 4.0, height: 3.0, color: "藍色")
]

for shape in shapes {
    shape.draw()
    print("  面積:\(String(format: "%.2f", shape.area()))")
}
▶ 輸出結果
畫一個 紅色 的圓形,半徑 5.0 面積:78.54 畫一個 藍色 的矩形 4.0 × 3.0 面積:12.00
進階章節

非同步並發

Swift 5.5+ 引入的 async/await、Task 和 Actor 讓並發程式設計更安全直觀。

Swift 5.5+

⚡ async / await

concurrency.swift
import Foundation

// 定義非同步函式
func fetchUserName(id: Int) async throws -> String {
    // 模擬網路延遲
    try await Task.sleep(nanoseconds: 1_000_000_000)
    
    let users = [1: "Alice", 2: "Bob", 3: "Charlie"]
    guard let name = users[id] else {
        throw URLError(.badURL)
    }
    return name
}

// 並發執行多個非同步任務
func fetchMultipleUsers() async {
    async let user1 = fetchUserName(id: 1)
    async let user2 = fetchUserName(id: 2)
    
    // 等待兩個任務都完成
    do {
        let (name1, name2) = try await (user1, user2)
        print("用戶 1:\(name1)")
        print("用戶 2:\(name2)")
    } catch {
        print("錯誤:\(error)")
    }
}

// Task - 啟動非同步任務
Task {
    await fetchMultipleUsers()
}

// Actor - 執行緒安全的共享狀態
actor BankAccount {
    private var balance: Double = 0
    
    func deposit(_ amount: Double) {
        balance += amount
        print("存入 \(amount),餘額:\(balance)")
    }
    
    func withdraw(_ amount: Double) -> Bool {
        guard balance >= amount else {
            print("餘額不足!")
            return false
        }
        balance -= amount
        print("提款 \(amount),餘額:\(balance)")
        return true
    }
}

// 使用 Actor
Task {
    let account = BankAccount()
    await account.deposit(1000)
    await account.withdraw(300)
    await account.withdraw(800) // 餘額不足
}
關於 async/await非同步程式碼需要在 Xcode Playground 或 iOS App 環境中執行,本教學的線上示例無法模擬真實的非同步行為,但語法結構與實際使用完全相同。

🔄 結構化並發 Structured Concurrency

概念說明使用場景
async func宣告非同步函式需要等待的操作(網路、檔案)
await等待非同步結果呼叫 async 函式時使用
async let並發啟動多個任務同時執行多個獨立請求
Task建立非同步任務從同步程式碼啟動非同步工作
TaskGroup動態並發任務組批量處理不定數量的任務
actor執行緒安全的類別共享狀態的並發安全保護
第十一章

字典 Dictionary

字典是鍵值對的集合,提供 O(1) 的查詢速度,非常適合快速查找的場景。

📖 建立與操作字典

dictionaries.swift
// 建立字典
var scores: [String: Int] = ["Alice": 95, "Bob": 82, "Charlie": 78]
var capitals = ["台灣": "台北", "日本": "東京", "美國": "華盛頓"]

// 讀取(返回 Optional)
if let aliceScore = scores["Alice"] {
    print("Alice 的分數:\(aliceScore)")
}

// 使用 ?? 提供預設值
let davidScore = scores["David"] ?? 0
print("David 的分數:\(davidScore)")

// 新增 / 修改
scores["David"] = 90
scores["Alice"] = 98  // 修改

// 刪除
scores.removeValue(forKey: "Bob")
scores["Charlie"] = nil  // 另一種刪除方式

print("字典:\(scores)")
print("人數:\(scores.count)")

// 遍歷字典
for (name, score) in scores.sorted(by: { $0.value > $1.value }) {
    print("\(name): \(score) 分")
}

// 取出所有鍵 / 值
print("所有人:\(Array(scores.keys))")
print("所有分數:\(Array(scores.values))")
▶ 輸出結果
Alice 的分數:95 David 的分數:0 字典:["Alice": 98, "David": 90] 人數:2 Alice: 98 分 David: 90 分 所有人:["Alice", "David"] 所有分數:[98, 90]
第十二章

集合 Set

Set 是無序且唯一元素的集合,支援數學集合運算,適合去重和快速查找。

🔵 Set 基本操作

sets.swift
// 建立 Set(需明確型別標注)
var fruits: Set = ["蘋果", "香蕉", "葡萄", "蘋果"]
// 重複的「蘋果」只會存一個
print(fruits)
print("元素數量:\(fruits.count)")

// 集合運算
let setA: Set = [1, 2, 3, 4, 5]
let setB: Set = [3, 4, 5, 6, 7]

print("聯集:\(setA.union(setB).sorted())")
print("交集:\(setA.intersection(setB).sorted())")
print("差集:\(setA.subtracting(setB).sorted())")
print("對稱差集:\(setA.symmetricDifference(setB).sorted())")

// 子集 / 超集 判斷
let setC: Set = [3, 4]
print("setC 是 setA 的子集:\(setC.isSubset(of: setA))")
print("setA 是 setC 的超集:\(setA.isSuperset(of: setC))")

// 陣列去重
let arr = [1, 2, 2, 3, 3, 3, 4]
let unique = Array(Set(arr)).sorted()
print("去重後:\(unique)")
▶ 輸出結果
["蘋果", "香蕉", "葡萄"] 元素數量:3 聯集:[1, 2, 3, 4, 5, 6, 7] 交集:[3, 4, 5] 差集:[1, 2] 對稱差集:[1, 2, 6, 7] setC 是 setA 的子集:true setA 是 setC 的超集:true 去重後:[1, 2, 3, 4]
第十五章

選擇型別 Optional

Optional 是 Swift 的安全機制,用來表示「值可能不存在」,避免空指針崩潰。

❓ Optional 完整教學

optionals.swift
// Optional 宣告
var name: String? = "Swift"
var age: Int? = nil

// 1. 可選鏈 Optional Chaining
let count = name?.count  // 若 name 為 nil 則返回 nil
print(count ?? 0)

// 2. if let 安全解包
if let unwrappedName = name {
    print("名字:\(unwrappedName)")
}

// 3. guard let 早退
func printAge(_ age: Int?) {
    guard let age = age else {
        print("年齡不明")
        return
    }
    print("年齡:\(age)")
}
printAge(25)
printAge(nil)

// 4. ?? 空合運算子
let displayAge = age ?? 18
print("顯示年齡:\(displayAge)")

// 5. 可選鏈連鎖
struct Address { var city: String? }
struct Person { var address: Address? }

let person = Person(address: Address(city: "台北"))
let city = person.address?.city ?? "未知城市"
print("城市:\(city)")

// 6. 強制解包(謹慎使用!)
let safeValue: String? = "確定有值"
print(safeValue!)  // 確定有值時才用 !
▶ 輸出結果
5 名字:Swift 年齡:25 年齡不明 顯示年齡:18 城市:台北 確定有值
第十八章

列舉 Enum

Swift 的 enum 是強大的型別,支援關聯值、原始值和方法,遠超其他語言的列舉。

🏷️ 列舉進階用法

enums.swift
// 基本列舉
enum Direction {
    case north, south, east, west
}

let dir = Direction.north
print(dir)

// 帶原始值的列舉
enum Planet: Int {
    case mercury = 1, venus, earth, mars
    
    var description: String {
        switch self {
        case .earth: return "我們的家鄉 🌍"
        case .mars:  return "未來的移民地 🔴"
        default:     return "神秘星球"
        }
    }
}

let earth = Planet.earth
print("\(earth):\(earth.description)")
print("地球是第 \(earth.rawValue) 顆行星")

// 帶關聯值的列舉(Swift 最強大的特性之一)
enum PaymentMethod {
    case cash(amount: Double)
    case creditCard(number: String, expiry: String)
    case applePay(phoneLastFour: String)
}

let payment = PaymentMethod.creditCard(number: "1234", expiry: "12/26")

switch payment {
case .cash(let amount):
    print("現金:\(amount) 元")
case .creditCard(let num, let exp):
    print("信用卡:\(num),到期:\(exp)")
case .applePay(let phone):
    print("Apple Pay:\(phone)")
}
▶ 輸出結果
north earth:我們的家鄉 🌍 地球是第 3 顆行星 信用卡:1234,到期:12/26
進階章節

泛型 Generics

泛型讓你撰寫可重複使用的程式碼,同時保持型別安全,是 Swift 標準庫的基礎。

🔷 泛型函式與型別

generics.swift
// 泛型函式
func swap(_ a: inout T, _ b: inout T) {
    let temp = a
    a = b
    b = temp
}

var x = 10, y = 20
swap(&x, &y)
print("x=\(x), y=\(y)")

var str1 = "Hello", str2 = "World"
swap(&str1, &str2)
print("\(str1) \(str2)")

// 泛型型別(Stack 堆疊)
struct Stack {
    private var items: [Element] = []
    
    mutating func push(_ item: Element) {
        items.append(item)
    }
    
    mutating func pop() -> Element? {
        return items.popLast()
    }
    
    var top: Element? {
        return items.last
    }
    
    var isEmpty: Bool { items.isEmpty }
    var count: Int { items.count }
}

var stack = Stack()
stack.push(1)
stack.push(2)
stack.push(3)
print("堆疊頂端:\(stack.top!)")
print("彈出:\(stack.pop()!)")
print("剩餘:\(stack.count) 個")

// 型別約束
func findMax(_ array: [T]) -> T? {
    return array.max()
}

print(findMax([3, 1, 4, 1, 5, 9])!)
print(findMax(["banana", "apple", "cherry"])!)
▶ 輸出結果
x=20, y=10 World Hello 堆疊頂端:3 彈出:3 剩餘:2 個 9 cherry
進階章節

錯誤處理

Swift 提供完整的錯誤處理機制,讓你的程式在面對異常情況時優雅地應對。

🛡️ throw / try / catch

error_handling.swift
// 定義錯誤型別
enum LoginError: Error {
    case emptyUsername
    case emptyPassword
    case invalidCredentials
    case accountLocked(reason: String)
}

// 會拋出錯誤的函式
func login(username: String, password: String) throws -> String {
    guard !username.isEmpty else { throw LoginError.emptyUsername }
    guard !password.isEmpty else { throw LoginError.emptyPassword }
    
    if username == "admin" && password == "swift123" {
        return "歡迎回來,\(username)!"
    } else if username == "blocked" {
        throw LoginError.accountLocked(reason: "多次輸入錯誤密碼")
    } else {
        throw LoginError.invalidCredentials
    }
}

// do-try-catch 處理錯誤
func attemptLogin(_ user: String, _ pass: String) {
    do {
        let message = try login(username: user, password: pass)
        print("✅ \(message)")
    } catch LoginError.emptyUsername {
        print("❌ 請輸入用戶名")
    } catch LoginError.emptyPassword {
        print("❌ 請輸入密碼")
    } catch LoginError.invalidCredentials {
        print("❌ 用戶名或密碼錯誤")
    } catch LoginError.accountLocked(let reason) {
        print("🔒 帳號已鎖定:\(reason)")
    } catch {
        print("未知錯誤:\(error)")
    }
}

attemptLogin("admin", "swift123")
attemptLogin("", "pass")
attemptLogin("admin", "wrong")
attemptLogin("blocked", "pass")

// defer - 確保執行清理工作
func readFile(name: String) throws {
    print("📂 開啟檔案:\(name)")
    defer {
        print("📁 關閉檔案:\(name)")  // 一定會執行
    }
    
    // 模擬讀取
    print("📖 讀取內容...")
    if name == "secret.txt" {
        throw LoginError.invalidCredentials
    }
    print("✅ 讀取完成")
}

try? readFile(name: "data.txt")
print("---")
try? readFile(name: "secret.txt")
▶ 輸出結果
✅ 歡迎回來,admin! ❌ 請輸入用戶名 ❌ 用戶名或密碼錯誤 🔒 帳號已鎖定:多次輸入錯誤密碼 📂 開啟檔案:data.txt 📖 讀取內容... ✅ 讀取完成 📁 關閉檔案:data.txt --- 📂 開啟檔案:secret.txt 📖 讀取內容... 📁 關閉檔案:secret.txt
綜合測驗

Swift 知識測驗

測試你對 Swift 的掌握程度!完成後查看解說,鞏固學習成果。

問題 1 / 8 基礎
在 Swift 中,哪個關鍵字用來宣告不可更改的常數?
問題 2 / 8 基礎
以下哪段程式碼會輸出 Hello, Swift!
問題 3 / 8 基礎
在 Swift 中,Int? 代表什麼型別?
問題 4 / 8 中階
以下 Swift 程式碼的輸出是什麼?
let arr = [1,2,3,4,5].filter { $0 % 2 == 0 }.map { $0 * 3 }
print(arr)
問題 5 / 8 中階
Swift 中 structclass 最主要的差異是什麼?
問題 6 / 8 進階
以下哪個是正確的 Swift 閉包語法,用來過濾大於 5 的數字?
問題 7 / 8 進階
Swift 的 guard letif let 最主要的差異是什麼?
問題 8 / 8 進階
Swift 並發中,actor 的主要用途是什麼?