owned this note
owned this note
Published
Linked with GitHub
# Variables 變數
## 設定 Playground
- 新建一個空白的 Playground。
- 透過 `import Foundation` 引入 Foundation 庫,用於基本的 Swift 操作。
## 變數與常數的宣告
- Swift 中有兩種關鍵字來宣告變數:`let` 和 `var`。
- `let` 用於宣告常數,不可重新賦值。
- `var` 用於宣告變數,可以重新賦值。
- **例子:**
- `let myName = "Vandad"`
- `var yourName = "Foo"`
## 變數與常數的不同
- `let` 變數不能重新賦值,而 `var` 變數可以重新賦值。
- `let` 常數的內部值不能被修改,而 `var` 變數的內部值可以被修改。
- **例子:**
- `let names = ["Vandad", "Foo"]` 則 `names` 不能被修改。
- `var names = ["Vandad", "Foo"]` 則 `names` 可以用 `.append()` 方法新增元素。
## 數組的操作
- Swift 中的數組(Array)是結構體(structure),屬於值類型(value types)。
- **例子:**
- `var names = ["Vandad", "Foo"]`
- `names.append("Bar")` 可以新增元素。
- 如果 `names` 是用 `let` 宣告,則無法使用 `append` 方法。
## 值類型與參考類型
- Swift 中的結構體是值類型,類別是參考類型。
- **值類型:**
- 當變數賦值給另一個變數時,會複製其值。
- 例如:`let moreNames = ["Foo", "Bar"]` 和 `var copy = moreNames`,修改 `copy` 不會影響 `moreNames`。
- **參考類型:**
- 當變數賦值給另一個變數時,兩個變數引用同一個實例。
- 例如:`let oldArray = NSMutableArray(array: ["Foo", "Bar"])` 和 `var newArray = oldArray`,修改 `newArray` 會影響 `oldArray`。
## 內部可變性
- `let` 變數如果持有的是一個類別實例,該實例的內部值仍然可以被修改。
- **例子:**
- `let oldArray = NSMutableArray(array: ["Foo", "Bar"])`
- `oldArray.add("Baz")`,`oldArray` 內部值會被修改。
## 範例程式碼與說明
```swift
let someNames = ["Foo", "Bar"]
func changeArray(array: NSArray) {
let mutableArray = array as! NSMutableArray
mutableArray.add("Baz")
}
changeArray(array: someNames)
print(someNames) // 會列印 ["Foo", "Bar", "Baz"]
```
- 此例說明了 `NSArray` 轉型為 `NSMutableArray` 後,內部值可以被修改。
## 注意事項
- 在 Swift 中,確保理解 `let` 和 `var` 的不同,以及值類型與參考類型的操作方式。
- 熟悉這些概念對於後續學習 Swift 的其他功能和特性非常重要。
# Operators 運算子
## 設定 Playground
- 新建一個空白的 Playground。
- 透過 `import Foundation` 引入 Foundation 庫。
## 基本運算子
- 宣告常數:`let myAge = 22` 和 `let yourAge = 20`
- 比較運算子:`>` 和 `<`
- **例子:**
```swift
if myAge > yourAge {
print("I'm older than you")
} else if myAge < yourAge {
print("I'm younger than you")
} else {
print("We are the same age")
}
```
## 算術運算子
- 加法運算子:`+`
- **例子:**
```swift
let myMotherAge = myAge + 30
```
- 乘法運算子:`*`
- **例子:**
```swift
let doubleMyAge = myAge * 2
```
## 運算子類型
- Swift 中有三種類型的運算子:
- **單目前置運算子(Unary Prefix)**
- **單目後置運算子(Unary Postfix)**
- **雙目中置運算子(Binary Infix)**
### 單目前置運算子(Unary Prefix)
- 只作用於一個值,位於值之前。
- **例子:**
```swift
let foo = true
let notFoo = !foo
```
### 單目後置運算子(Unary Postfix)
- 只作用於一個值,位於值之後。
- **例子:**
```swift
let name: String? = "Vandad"
let unwrappedName = name!
```
### 雙目中置運算子(Binary Infix)
- 作用於兩個值,位於兩值之間。
- **例子:**
```swift
let result = 1 + 2
let fullName = "Foo" + " " + "Bar"
```
## 三元運算子(Ternary Operator)
- 格式:`condition ? value_if_true : value_if_false`
- **例子:**
```swift
let age = 30
let message = age >= 18 ? "You are an adult" : "You are not yet an adult"
```
## 重點整理
- 運算子是特別的函數,Swift 將其視為特別的函數。
- **單目前置運算子**:只作用於一個值且位於值之前。
- **單目後置運算子**:只作用於一個值且位於值之後。
- **雙目中置運算子**:作用於兩個值且位於兩值之間。
- **三元運算子**:條件運算子,用於簡化條件判斷。
# If and Else 條件判斷
## 設定 Playground
- 新建一個空白的 Playground。
- 透過 `import Foundation` 引入 Foundation 庫。
## 基本 If 和 Else 語句
- **例子:**
```swift
let myName = "vandad"
if myName == "Vandad" {
print("Your name is \(myName)")
} else {
print("Oops, I guessed it wrong")
}
```
- 比較字符串 `myName` 是否等於 `"Vandad"`。
- 使用 `else` 處理不符合條件的情況。
## Else If 語句
- **例子:**
```swift
if myName == "Vandad" {
print("Now I guessed it correctly")
} else if myName == "Foo" {
print("Are you Foo?")
} else {
print("Okay, I give up")
}
```
- 使用 `else if` 增加更多條件分支。
## 多條件判斷
- 使用 `&&`(邏輯與)運算符。
```swift
if myName == "Vandad" && myAge == 30 {
print("Name is Vandad and age is 30")
} else if myAge == 20 {
print("I only guessed the age right")
} else {
print("I don't know what I'm doing")
}
```
- 同時檢查多個條件。
## 邏輯運算符
- **OR 運算符 (`||`)**
```swift
if myAge == 20 || myName == "Foo" {
print("Either age is 20, name is Foo, or both")
}
```
- 至少一個條件成立即執行。
## 邏輯運算順序
- 需要小心處理邏輯運算符,否則可能會導致錯誤的結果。
- **例子:**
```swift
if (myName == "Vandad" && myAge == 22) || (yourName == "Foo" || yourAge == 19) {
print("Complex condition met")
} else {
print("Condition not met")
}
```
- 使用括號來明確運算順序。
## 常見錯誤
- **例子:**
```swift
if myAge == 20 || myName == "Foo" {
print("Either age is 20, name is Foo, or both")
} else if myName == "Vandad" || myAge == 20 {
print("Too late to get in this class")
}
```
- 注意 `if` 條件判斷的邏輯。
## 重點整理
- **基本用法:**
- `if` 語句用於條件判斷。
- `else if` 和 `else` 用於處理多個條件分支。
- **邏輯運算符:**
- `&&` 用於與條件,要求所有條件都成立。
- `||` 用於或條件,要求至少一個條件成立。
- **複雜條件判斷:**
- 使用括號來確保運算順序正確。
- **良好習慣:**
- 避免過於複雜的條件判斷,保持程式碼易讀。
- 與團隊協作時,統一條件判斷的書寫風格。
# Functions 函數
## 設定 Playground
- 新建一個空白的 Playground。
- 透過 `import Foundation` 引入 Foundation 庫。
## 基本函數
- **無參數與無返回值的函數**
```swift
func noArgumentsAndNoReturnValue() {
print("I don't know what I'm doing")
}
noArgumentsAndNoReturnValue()
```
- 使用 `func` 關鍵字定義函數。
- 函數名稱使用駝峰式命名法。
- 沒有參數和返回值的函數。
## 帶參數的函數
- **有參數無返回值的函數**
```swift
func plusTwo(value: Int) {
let newValue = value + 2
print(newValue)
}
plusTwo(value: 30)
```
- 定義函數參數名稱及其類型。
- 參數傳遞。
## 帶返回值的函數
- **有參數有返回值的函數**
```swift
func newPlusTwo(value: Int) -> Int {
return value + 2
}
let result = newPlusTwo(value: 30)
print(result)
```
## 多參數函數
- **多參數並返回值的函數**
```swift
func customAdd(value1: Int, value2: Int) -> Int {
return value1 + value2
}
let sum = customAdd(value1: 10, value2: 20)
print(sum)
```
## 參數名稱
- **內部和外部參數名稱**
```swift
func customSubtract(_ lhs: Int, _ rhs: Int) -> Int {
return lhs - rhs
}
let difference = customSubtract(20, 10)
print(difference)
```
## 可丟棄返回值的函數
- **使用 `@discardableResult` 註解**
```swift
@discardableResult
func myCustomAdd(_ lhs: Int, _ rhs: Int) -> Int {
return lhs + rhs
}
myCustomAdd(20, 30)
```
## 函數中的函數
- **內部函數的使用**
```swift
func doSomethingComplicated(with value: Int) -> Int {
func mainLogic(_ value: Int) -> Int {
return value + 2
}
return mainLogic(value + 3)
}
let result = doSomethingComplicated(with: 30)
print(result)
```
## 帶預設值的參數
- **預設參數值的函數**
```swift
func getFullName(firstName: String = "Foo", lastName: String = "Bar") -> String {
return "\(firstName) \(lastName)"
}
let fullName1 = getFullName()
let fullName2 = getFullName(firstName: "Baz")
let fullName3 = getFullName(lastName: "Qux")
let fullName4 = getFullName(firstName: "Baz", lastName: "Qux")
print(fullName1, fullName2, fullName3, fullName4)
```
## 重點整理
- **函數定義:**
- 使用 `func` 關鍵字定義函數。
- 函數名稱使用駝峰式命名法。
- 可以有參數和返回值。
- **參數傳遞:**
- 定義參數名稱及其類型。
- 可以有內部和外部參數名稱。
- **返回值:**
- 使用 `->` 指定返回值類型。
- 可以使用 `@discardableResult` 註解來允許丟棄返回值。
- **內部函數:**
- 函數內可以定義其他函數。
- **預設參數值:**
- 可以為參數設置預設值,允許函數在沒有傳遞所有參數的情況下被調用。
# Closures 閉包
## 設定 Playground
- 新建一個空白的 Playground。
- 透過 `import Foundation` 引入 Foundation 庫。
## 基本閉包
- **閉包的定義與使用**
```swift
let add: (Int, Int) -> Int = { (leftHandSide: Int, rightHandSide: Int) -> Int in
return leftHandSide + rightHandSide
}
let result = add(20, 30)
print(result) // 50
```
## 閉包作為參數
- **將閉包作為參數傳遞給函數**
```swift
func customAdd(lhs: Int, rhs: Int, using function: (Int, Int) -> Int) -> Int {
return function(lhs, rhs)
}
let sum = customAdd(lhs: 20, rhs: 30) { (leftHandSide, rightHandSide) -> Int in
return leftHandSide + rightHandSide
}
print(sum) // 50
```
## 閉包簡化
- **移除閉包的類型與返回值**
```swift
let simplifiedSum = customAdd(lhs: 20, rhs: 30) { lhs, rhs in
lhs + rhs
}
print(simplifiedSum) // 50
```
- **使用 Swift 的縮寫參數名**
```swift
let shorthandSum = customAdd(lhs: 20, rhs: 30) {
$0 + $1
}
print(shorthandSum) // 50
```
## 運算符作為閉包
- **傳遞運算符作為閉包參數**
```swift
let ascendingAges = [30, 20, 19, 40].sorted(by: <)
let descendingAges = [30, 20, 19, 40].sorted(by: >)
print(ascendingAges) // [19, 20, 30, 40]
print(descendingAges) // [40, 30, 20, 19]
```
## 使用函數作為閉包
- **將現有函數作為參數傳遞給閉包**
```swift
func addTen(to value: Int) -> Int {
return value + 10
}
func addTwenty(to value: Int) -> Int {
return value + 20
}
func doAddition(on value: Int, using function: (Int) -> Int) -> Int {
return function(value)
}
let result1 = doAddition(on: 20, using: addTen)
let result2 = doAddition(on: 20, using: addTwenty)
print(result1) // 30
print(result2) // 40
```
## 重點整理
- **閉包定義:**
- 閉包是一種內聯函數,可以傳遞給其他函數使用。
- **閉包作為參數:**
- 可以將閉包作為函數的參數,並在函數內部調用。
- **閉包簡化:**
- 可以簡化閉包的類型與返回值定義,使用縮寫參數名。
- **運算符與函數作為閉包:**
- 可以將運算符和現有函數作為閉包參數傳遞給其他函數。
# Structures 結構
## 設定 Playground
- 新建一個空白的 Playground。
- 透過 `import Foundation` 引入 Foundation 庫。
## 基本結構
- **結構的定義與實例化**
```swift
struct Person {
let name: String
var age: Int
}
let person = Person(name: "Foo", age: 20)
print(person.name) // Foo
print(person.age) // 20
```
## 自定義初始化函數
- **自定義初始化函數**
```swift
struct CommodoreComputer {
let name: String
let manufacturer: String
init(name: String) {
self.name = name
self.manufacturer = "Commodore"
}
}
let c64 = CommodoreComputer(name: "C64")
print(c64.name) // C64
print(c64.manufacturer) // Commodore
```
## 計算屬性
- **定義計算屬性**
```swift
struct Person2 {
let firstName: String
let lastName: String
var fullName: String {
return "\(firstName) \(lastName)"
}
}
let person2 = Person2(firstName: "Foo", lastName: "Bar")
print(person2.fullName) // Foo Bar
```
## 變異方法
- **使用變異方法改變結構的屬性**
```swift
struct Car {
var currentSpeed: Int
mutating func drive(at speed: Int) {
currentSpeed = speed
}
}
var car = Car(currentSpeed: 10)
car.drive(at: 30)
print(car.currentSpeed) // 30
```
## 結構複製
- **結構的值類型行為**
```swift
struct Car {
var currentSpeed: Int
}
var car1 = Car(currentSpeed: 10)
var car2 = car1
car2.currentSpeed = 20
print(car1.currentSpeed) // 10
print(car2.currentSpeed) // 20
```
## 自定義複製
- **實現自定義複製方法**
```swift
struct Bike {
let manufacturer: String
let currentSpeed: Int
func copy(with currentSpeed: Int) -> Bike {
return Bike(manufacturer: self.manufacturer, currentSpeed: currentSpeed)
}
}
let bike1 = Bike(manufacturer: "Harley Davidson", currentSpeed: 20)
let bike2 = bike1.copy(with: 30)
print(bike1.currentSpeed) // 20
print(bike2.currentSpeed) // 30
```
## 重點整理
- **基本結構:**
- 使用 `struct` 關鍵字定義結構。
- 可以包含常量和變量屬性。
- **自定義初始化函數:**
- 可以創建自定義初始化函數。
- 使用 `self` 關鍵字來區分屬性和參數。
- **計算屬性:**
- 可以使用計算屬性來實現動態計算的值。
- **變異方法:**
- 使用 `mutating` 關鍵字標記方法以允許修改屬性。
- **結構的值類型行為:**
- 結構是值類型,複製時會創建副本。
- **自定義複製:**
- 可以實現自定義方法來創建結構的複製。
# Enumerations 列舉
## 設定 Playground
- 新建一個空白的 Playground。
- 透過 `import Foundation` 引入 Foundation 庫。
## 基本列舉
- **定義與使用列舉**
```swift
enum Animals {
case cat
case dog
case rabbit
}
let pet = Animals.cat
print(pet) // cat
```
## 使用 Switch 進行列舉比較
- **用 Switch 語句比較列舉**
```swift
switch pet {
case .cat:
print("This is a cat")
case .dog:
print("This is a dog")
case .rabbit:
print("This is a rabbit")
}
```
## 列舉中的 Associated Values
- **定義與使用包含關聯值的列舉**
```swift
enum Shortcut {
case fileOrFolder(path: URL, name: String)
case wwwURL(path: URL)
case song(artist: String, songName: String)
}
let shortcut = Shortcut.wwwURL(path: URL(string: "https://apple.com")!)
```
## 列舉中的 Switch 與 Associated Values
- **在 Switch 語句中使用關聯值**
```swift
switch shortcut {
case .fileOrFolder(let path, let name):
print("File or folder: \(name) at \(path)")
case .wwwURL(let path):
print("URL: \(path)")
case .song(let artist, let songName):
print("Song: \(songName) by \(artist)")
}
```
## 列舉中的 Raw Values
- **定義與使用包含原始值的列舉**
```swift
enum FamilyMember: String {
case father = "Dad"
case mother = "Mom"
case brother = "Bro"
case sister = "Sis"
}
let member = FamilyMember.father
print(member.rawValue) // Dad
```
## 透過 Protocol 取得所有列舉案例
- **使用 CaseIterable Protocol**
```swift
enum FavoriteEmoji: String, CaseIterable {
case blush = "😊"
case rocket = "🚀"
case fire = "🔥"
}
for emoji in FavoriteEmoji.allCases {
print(emoji.rawValue)
}
```
## 變異方法
- **定義與使用變異方法**
```swift
enum Height {
case short, medium, long
mutating func makeLong() {
self = .long
}
}
var myHeight = Height.medium
myHeight.makeLong()
print(myHeight) // long
```
## 其他進階功能
- **定義間接列舉或遞迴列舉**
```swift
indirect enum IntOperation {
case addition(Int, Int)
case subtraction(Int, Int)
case freehand(IntOperation)
}
```
## 重點整理
- **基本列舉:**
- 使用 `enum` 關鍵字定義列舉。
- 列舉中的案例使用 `case` 關鍵字定義。
- **Switch 語句:**
- 使用 Switch 語句來比較列舉值。
- 可以用 `default` 關鍵字處理未定義的案例。
- **Associated Values:**
- 列舉案例可以有關聯值。
- 使用 Switch 語句處理關聯值。
- **Raw Values:**
- 列舉案例可以有原始值。
- 使用 `.rawValue` 獲取列舉案例的原始值。
- **CaseIterable Protocol:**
- 使用 `CaseIterable` Protocol 獲取所有列舉案例。
- **變異方法:**
- 使用 `mutating` 關鍵字定義變異方法。
- 可以在變異方法中改變列舉的值。
- **間接列舉:**
- 使用 `indirect` 關鍵字定義遞迴列舉。
# Classes 類別
## 基本介紹
- **類別與結構的區別**
- 類別是參考類型 (reference type),而結構是值類型 (value type)。
- 類別允許在內部進行可變性 (mutability),不需要使用 `mutating` 關鍵字。
## 定義類別
- **簡單類別定義與初始化**
```swift
class Person {
var name: String
var age: Int
init(name: String, age: Int) {
self.name = name
self.age = age
}
func increaseAge() {
self.age += 1
}
}
let foo = Person(name: "Foo", age: 20)
print(foo.age) // 20
foo.increaseAge()
print(foo.age) // 21
```
## 參考類型
- **參考類型示例**
```swift
let bar = foo
bar.increaseAge()
print(foo.age) // 22
print(bar.age) // 22
```
## 等於運算符 (Equality Operators)
- **使用三個等號比較參考**
```swift
if foo === bar {
print("foo and bar point to the same instance")
} else {
print("foo and bar do not point to the same instance")
}
```
## 繼承 (Inheritance)
- **定義與使用繼承**
```swift
class Vehicle {
func goVroom() {
print("Vroom vroom")
}
}
class Car: Vehicle {}
let car = Car()
car.goVroom() // Vroom vroom
```
## 私有 Setter
- **定義與使用私有 Setter**
```swift
class Person2 {
private(set) var age: Int
init(age: Int) {
self.age = age
}
func increaseAge() {
self.age += 1
}
}
let baz = Person2(age: 20)
print(baz.age) // 20
// baz.age += 1 // 這行會產生錯誤
baz.increaseAge()
print(baz.age) // 21
```
## 指定初始化器與便利初始化器
- **指定初始化器 (Designated Initializers)**
```swift
class Tesla {
let manufacturer: String
var model: String
var year: Int
init(model: String, year: Int) {
self.manufacturer = "Tesla"
self.model = model
self.year = year
}
}
```
- **便利初始化器 (Convenience Initializers)**
```swift
class Tesla {
let manufacturer: String
var model: String
var year: Int
init(model: String, year: Int) {
self.manufacturer = "Tesla"
self.model = model
self.year = year
}
convenience init(model: String) {
self.init(model: model, year: 2023)
}
}
```
## 方法內變異與參考
- **類別的參考行為**
```swift
let fubar = Person2(age: 20)
func doSomething(with person: Person2) {
person.increaseAge()
}
doSomething(with: fubar)
print(fubar.age) // 21
```
## 解初始化器 (Deinitializers)
- **定義與使用解初始化器**
```swift
class MyClass {
init() {
print("Initialized")
}
deinit {
print("Deinitialized")
}
func doSomething() {
print("Doing something")
}
}
do {
let myClass = MyClass()
myClass.doSomething()
}
// 這裡將會打印 "Deinitialized" 因為作用域結束後,myClass 將被釋放。
```
## 重點整理
- **基本類別:**
- 使用 `class` 關鍵字定義類別。
- 類別是參考類型,可以在內部進行變更。
- **繼承:**
- 類別可以繼承其他類別,並且繼承其方法與屬性。
- **私有 Setter:**
- 使用 `private(set)` 關鍵字定義只能在內部變更的屬性。
- **初始化器:**
- 類別需要定義初始化器,並且可以有指定初始化器與便利初始化器。
- **參考行為:**
- 類別的參考行為導致多個變數可以指向同一個實例。
- **解初始化器:**
- 解初始化器在實例被釋放時調用,用於清理資源。
# Protocols 協議
## 介紹
- **定義**:Protocols 是一種特定的對象,類似於 Java 中的接口(interface)。
- **作用**:定義一組規則,對象必須遵循這些規則。
## 定義協議
- **基本定義**
```swift
protocol CanBreathe {
func breathe()
}
```
## 類別和結構遵循協議
- **結構遵循協議**
```swift
struct Animal: CanBreathe {
func breathe() {
print("Animal breathing")
}
}
let dog = Animal()
dog.breathe() // Animal breathing
```
- **類別遵循協議**
```swift
struct Person: CanBreathe {
func breathe() {
print("Person breathing")
}
}
let foo = Person()
foo.breathe() // Person breathing
```
## 協議擴展
- **擴展協議以提供默認實現**
```swift
protocol CanJump {
func jump()
}
extension CanJump {
func jump() {
print("Jumping")
}
}
struct Cat: CanJump {}
let whiskers = Cat()
whiskers.jump() // Jumping
```
## 協議中的屬性
- **定義協議屬性**
```swift
protocol HasName {
var name: String { get }
var age: Int { get set }
}
struct Dog: HasName {
let name: String
var age: Int
}
let woof = Dog(name: "Woof", age: 10)
print(woof.name) // Woof
print(woof.age) // 10
```
## 協議擴展中的方法
- **擴展協議以添加方法**
```swift
extension HasName {
func describeMe() -> String {
return "Your name is \(name) and you are \(age) years old."
}
mutating func increaseAge() {
age += 1
}
}
var woof = Dog(name: "Woof", age: 10)
print(woof.describeMe()) // Your name is Woof and you are 10 years old.
woof.increaseAge()
print(woof.age) // 11
```
## 協議中的變異方法
- **定義變異方法**
```swift
protocol Vehicle {
var speed: Int { get set }
mutating func increaseSpeed(by value: Int)
}
extension Vehicle {
mutating func increaseSpeed(by value: Int) {
speed += value
}
}
struct Bike: Vehicle {
var speed = 0
}
var bike = Bike()
bike.increaseSpeed(by: 10)
print(bike.speed) // 10
```
## 檢查協議遵循
- **使用 `is` 檢查對象是否遵循某協議**
```swift
func describe(_ object: Any) {
if object is Vehicle {
print("Object conforms to the Vehicle protocol")
} else {
print("Object does not conform to the Vehicle protocol")
}
}
describe(bike) // Object conforms to the Vehicle protocol
```
## 使用 `as` 和 `as?` 進行類型轉換
- **條件類型轉換**
```swift
func increaseSpeedIfVehicle(_ object: Any) {
if let vehicle = object as? Vehicle {
vehicle.increaseSpeed(by: 20)
print(vehicle.speed)
} else {
print("This was not a vehicle")
}
}
increaseSpeedIfVehicle(bike) // 30 (after calling it twice)
```
## 參考類型與值類型的區別
- **類與結構在協議中的行為差異**
```swift
class Car: Vehicle {
var speed = 0
}
let car = Car()
increaseSpeedIfVehicle(car)
print(car.speed) // 20
```
## 小結
- **協議定義**:定義一組規則,結構或類別遵循這些規則。
- **協議擴展**:可以為協議提供默認的實現。
- **檢查和轉換**:使用 `is` 和 `as` 來檢查對象是否遵循協議,並進行條件類型轉換。
- **變異方法**:協議中的方法可以標記為變異,允許修改實例屬性。
# Extensions 擴展
## 介紹
- **定義**:Extensions 可以為現有類型添加功能,使得我們能夠擴展原有類型的能力,而無需修改其源代碼。
## 擴展數據類型
- **擴展整數類型**
```swift
extension Int {
func plusTwo() -> Int {
return self + 2
}
}
let value = 2
print(value.plusTwo()) // 4
```
## 為現有類型添加初始化器
- **為結構添加初始化器**
```swift
struct Person {
let firstName: String
let lastName: String
}
extension Person {
init(fullName: String) {
let components = fullName.split(separator: " ")
self.init(firstName: String(components.first ?? ""), lastName: String(components.last ?? ""))
}
}
let person = Person(fullName: "Foo Bar")
print(person.firstName) // Foo
print(person.lastName) // Bar
```
## 擴展協議並添加默認實現
- **擴展協議**
```swift
protocol GoesVroom {
var vroomValue: String { get }
func goVroom() -> String
}
extension GoesVroom {
func goVroom() -> String {
return "\(vroomValue) goes vroom"
}
}
struct Car: GoesVroom {
let manufacturer: String
let model: String
var vroomValue: String {
return "\(manufacturer) \(model)"
}
}
let modelX = Car(manufacturer: "Tesla", model: "Model X")
print(modelX.goVroom()) // Tesla Model X goes vroom
```
## 為類別添加便捷初始化器
- **擴展類別並添加便捷初始化器**
```swift
class MyDouble {
let value: Double
init(value: Double) {
self.value = value
}
}
extension MyDouble {
convenience init() {
self.init(value: 0)
}
}
let myDouble = MyDouble()
print(myDouble.value) // 0
```
## 擴展協議
- **擴展協議並添加新方法**
```swift
extension GoesVroom {
func goVroomVroomEvenMore() -> String {
return "\(vroomValue) is vrooming even more"
}
}
print(modelX.goVroomVroomEvenMore()) // Tesla Model X is vrooming even more
```
## 小結
- **擴展的強大功能**:
- 擴展數據類型:可以為現有數據類型添加方法。
- 添加初始化器:可以為現有類型添加初始化器而不破壞現有的初始化器。
- 擴展協議:可以為協議添加默認實現和新方法,使得所有遵循該協議的類型自動獲得這些新功能。
- 擴展類別:可以為類別添加便捷初始化器,增加類別的靈活性。
# Generics 泛型
## 介紹
- **定義**:泛型是一種強大的工具,允許我們編寫靈活且可重用的代碼,避免重複代碼。
- **目標**:希望能夠使用同一函數或類型來處理不同的數據類型,而不需要針對每種數據類型編寫重複的代碼。
## 基本範例
- **範例說明**:編寫一個可以接受任意數值類型的函數,並對兩個值進行運算。
```swift
func perform<T: Numeric>(_ lhs: T, _ rhs: T, using operation: (T, T) -> T) -> T {
return operation(lhs, rhs)
}
let sum = perform(10, 20, using: +) // 30
let difference = perform(20.0, 10.0, using: -) // 10.0
```
## 使用條件約束
- **範例說明**:為泛型添加條件約束,指定泛型參數必須符合某個協議。
```swift
func perform<T>(_ lhs: T, _ rhs: T, using operation: (T, T) -> T) -> T where T: Numeric {
return operation(lhs, rhs)
}
```
## 多個泛型參數
- **範例說明**:處理多個泛型參數的函數範例。
```swift
func swapValues<T>(_ a: inout T, _ b: inout T) {
let temp = a
a = b
b = temp
}
var a = 1, b = 2
swapValues(&a, &b)
print(a, b) // 2, 1
```
## 擴展泛型類型
- **範例說明**:擴展泛型類型(例如:陣列),並添加自定義方法。
```swift
extension Array where Element: Numeric {
func sum() -> Element {
return self.reduce(0, +)
}
}
let numbers = [1, 2, 3, 4, 5]
print(numbers.sum()) // 15
```
## 協議中的關聯類型
- **範例說明**:定義一個帶有關聯類型的協議,並實現泛型協議。
```swift
protocol Container {
associatedtype Item
var items: [Item] { get }
mutating func addItem(_ item: Item)
}
struct Stack<Element>: Container {
var items = [Element]()
mutating func addItem(_ item: Element) {
items.append(item)
}
}
var intStack = Stack<Int>()
intStack.addItem(3)
```
## 約束泛型擴展
- **範例說明**:對泛型擴展添加約束。
```swift
extension Container where Item == Int {
func sum() -> Int {
return items.reduce(0, +)
}
}
var intStack = Stack<Int>()
intStack.addItem(3)
intStack.addItem(5)
print(intStack.sum()) // 8
```
## 進階應用:使用泛型協議
- **範例說明**:定義一個泛型協議,並實現多種不同的類型。
```swift
protocol EquatableValue {
associatedtype ValueType: Equatable
var value: ValueType { get }
}
struct StringValue: EquatableValue {
var value: String
}
struct IntValue: EquatableValue {
var value: Int
}
```
## 小結
- **泛型的優點**:
- 代碼重用:避免重複代碼,減少維護成本。
- 靈活性:允許同一個函數或類型處理多種數據類型。
- 類型安全:在編譯時確保數據類型的正確性。
# Optionals 可選值
## 介紹
- **定義**:Optionals 表示一個值可能存在也可能不存在。
- **目的**:用來處理那些有可能為 `nil` 的情況,避免程式因為空指標異常而崩潰。
## 基本範例
- **範例說明**:函數接受一個可能為 `nil` 的整數,並將其乘以 2。
```swift
func multiplyByTwo(_ value: Int?) -> Int {
return (value ?? 0) * 2
}
print(multiplyByTwo(nil)) // 0
print(multiplyByTwo(4)) // 8
```
## Optional 判斷與解包
- **範例說明**:使用 `if let` 解包一個 Optional 值。
```swift
let age: Int? = nil
if let unwrappedAge = age {
print("Age is \(unwrappedAge)")
} else {
print("Age is nil")
}
```
- **Guard 解包**:使用 `guard let` 解包 Optional 值。
```swift
func checkAge(_ age: Int?) {
guard let unwrappedAge = age else {
print("Age is nil")
return
}
print("Age is \(unwrappedAge)")
}
checkAge(nil) // "Age is nil"
checkAge(10) // "Age is 10"
```
## Optional 的比較與操作
- **比較 Optional 值**:可以直接與值進行比較。
```swift
let number: Int? = 10
if number == 10 {
print("Number is 10")
} else {
print("Number is not 10")
}
```
- **Optional 連鎖**:用來安全地調用 Optional 屬性或方法。
```swift
struct Address {
var firstLine: String?
}
struct Person {
var name: String
var address: Address?
}
let person = Person(name: "Foo", address: nil)
if let firstLine = person.address?.firstLine {
print("Address is \(firstLine)")
} else {
print("No address available")
}
```
## Switch 語句處理 Optionals
- **範例說明**:使用 `switch` 語句處理 Optional。
```swift
let someValue: Int? = 42
switch someValue {
case .none:
print("Value is nil")
case .some(let value):
print("Value is \(value)")
}
```
## Optional Chaining 與模式匹配
- **範例說明**:使用 `where` 子句進行模式匹配。
```swift
let person = Person(name: "Bar", address: Address(firstLine: "Bar's Address"))
switch person.address?.firstLine {
case let firstLine? where firstLine.starts(with: "Bar"):
print("First line is \(firstLine)")
case let firstLine?:
print("First line did not match: \(firstLine)")
case nil:
print("Address is nil")
}
```
## 範例:Optionals 和 Guard 使用
- **範例說明**:函數使用 `guard` 來處理 Optional 值。
```swift
func getFullName(firstName: String, lastName: String?) -> String? {
guard let lastName = lastName else {
return nil
}
return "\(firstName) \(lastName)"
}
print(getFullName(firstName: "Foo", lastName: nil)) // nil
print(getFullName(firstName: "Foo", lastName: "Bar")) // "Foo Bar"
```
## 小結
- **Optionals 的優點**:
- 安全處理:避免空指標異常。
- 可讀性:程式碼更易讀,能清楚表示哪些值可能為 `nil`。
- 靈活性:允許開發者處理可選值情況,使程式更加健壯。
# Error Handling 錯誤處理
## 介紹
- **定義**:錯誤處理是讓程式碼能夠在遇到問題時通知調用者。
- **關鍵字**:`throw`、`try`、`do-catch`。
## 定義與捕獲錯誤
- **範例說明**:定義錯誤和捕獲錯誤。
```swift
struct Person {
var firstName: String?
var lastName: String?
enum Errors: Error {
case firstNameIsNil
case lastNameIsNil
case bothNamesAreNil
}
func getFullName() throws -> String {
switch (firstName, lastName) {
case (.none, .none):
throw Errors.bothNamesAreNil
case (.none, .some):
throw Errors.firstNameIsNil
case (.some, .none):
throw Errors.lastNameIsNil
case let (.some(firstName), .some(lastName)):
return "\(firstName) \(lastName)"
}
}
}
let foo = Person(firstName: "Foo", lastName: nil)
do {
let fullName = try foo.getFullName()
print(fullName)
} catch Person.Errors.firstNameIsNil {
print("First name is nil")
} catch Person.Errors.lastNameIsNil {
print("Last name is nil")
} catch Person.Errors.bothNamesAreNil {
print("Both names are nil")
} catch {
print("Some other error: \(error)")
}
```
## 錯誤類型與捕獲特定錯誤
- **範例說明**:捕獲特定類型的錯誤。
```swift
do {
let fullName = try foo.getFullName()
print(fullName)
} catch is Person.Errors {
print("Caught a Person.Errors")
} catch {
print("Some other error: \(error)")
}
```
## 擲出錯誤的初始化方法
- **範例說明**:在初始化方法中擲出錯誤。
```swift
struct Car {
let manufacturer: String
enum Errors: Error {
case invalidManufacturer
}
init(manufacturer: String) throws {
if manufacturer.isEmpty {
throw Errors.invalidManufacturer
}
self.manufacturer = manufacturer
}
}
do {
let myCar = try Car(manufacturer: "")
print(myCar.manufacturer)
} catch Car.Errors.invalidManufacturer {
print("Invalid manufacturer")
} catch {
print("Some other error: \(error)")
}
```
## 可選的 `try` 語法
- **範例說明**:使用可選的 `try?` 語法。
```swift
if let car = try? Car(manufacturer: "Tesla") {
print("Success: \(car.manufacturer)")
} else {
print("Failed to construct car")
}
```
## `try!` 強制解包
- **範例說明**:使用 `try!` 強制解包。
```swift
let car = try! Car(manufacturer: "Ford")
print(car.manufacturer)
```
## 結果類型 (`Result`)
- **範例說明**:使用 `Result` 類型處理錯誤。
```swift
enum IntegerErrors: Error {
case noPositiveIntegerBeforeThisValue
}
func getPreviousPositiveInteger(from value: Int) -> Result<Int, IntegerErrors> {
guard value > 0 else {
return .failure(.noPositiveIntegerBeforeThisValue)
}
return .success(value - 1)
}
func performGet(for value: Int) {
switch getPreviousPositiveInteger(from: value) {
case .success(let previousValue):
print("Previous value is \(previousValue)")
case .failure(let error):
switch error {
case .noPositiveIntegerBeforeThisValue:
print("No positive integer before this value")
}
}
}
performGet(for: 0)
performGet(for: 2)
```
## 捕獲和重新拋出錯誤 (`rethrows`)
- **範例說明**:使用 `rethrows` 語法。
```swift
func performOperation(with function: (Int, Int) throws -> Int, a: Int, b: Int) rethrows {
try function(a, b)
}
enum MathError: Error {
case divisionByZero
}
func divide(_ a: Int, by b: Int) throws -> Int {
if b == 0 {
throw MathError.divisionByZero
}
return a / b
}
do {
try performOperation(with: divide, a: 10, b: 0)
} catch MathError.divisionByZero {
print("Cannot divide by zero")
} catch {
print("Some other error: \(error)")
}
```
## 小結
- **錯誤處理的重要性**:確保程式在異常情況下能夠優雅地處理錯誤。
- **多種錯誤處理方式**:
- `do-catch` 語法
- `try?` 和 `try!`
- `Result` 類型
- `rethrows` 用於重拋錯誤的函數
# Collections 集合
## 介紹
- **定義**:集合是一組相關的數據。
- **常見類型**:陣列(Array)、集合(Set)、字典(Dictionary)。
## 陣列(Array)
- **定義**:有序的數據集合。
- **創建**:
```swift
let numbers = [1, 2, 3, 4]
```
- **操作**:
- 獲取第一個和最後一個元素:
```swift
let first = numbers.first
let last = numbers.last
```
- 計算元素數量:
```swift
let count = numbers.count
```
- 映射元素:
```swift
let negatedNumbers = numbers.map { $0 * -1 }
```
## 可變陣列(Mutable Array)
- **創建**:
```swift
var mutatingNumbers = [0, 1, 2]
```
- **操作**:
- 添加元素:
```swift
mutatingNumbers.append(3)
```
- 插入元素:
```swift
mutatingNumbers.insert(-1, at: 0)
```
- 插入另一個陣列:
```swift
mutatingNumbers.insert(contentsOf: [1, 2], at: 0)
```
## 遍歷陣列
- **基本遍歷**:
```swift
for value in numbers {
print(value)
}
```
- **條件遍歷**:
```swift
for value in numbers where value % 2 == 0 {
print(value)
}
```
## 映射(Map)
- **映射操作**:
```swift
let doubledNumbers = numbers.map { $0 * 2 }
let stringNumbers = numbers.map { String($0) }
```
## 過濾(Filter)
- **過濾操作**:
```swift
let filteredNumbers = numbers.filter { $0 >= 3 }
```
## CompactMap
- **CompactMap 操作**:
```swift
let optionalNumbers: [Int?] = [1, 2, nil, 4]
let nonNilNumbers = optionalNumbers.compactMap { $0 }
```
## 集合(Set)
- **定義**:不包含重複元素的無序集合。
- **創建**:
```swift
let uniqueNumbers: Set = [1, 2, 1, 2, 3]
```
- **操作**:
- 計算元素數量:
```swift
let count = uniqueNumbers.count
```
- CompactMap 操作:
```swift
let myNumbers: Set<Int?> = [1, 2, nil, 4, 5]
let notNilNumbers = Set(myNumbers.compactMap { $0 })
```
## 字典(Dictionary)
- **定義**:鍵值對集合。
- **創建**:
```swift
let userInfo: [String: Any] = [
"name": "Foo",
"age": 20,
"address": [
"line1": "Address Line 1",
"postcode": "12345"
]
]
```
- **操作**:
- 獲取值:
```swift
let name = userInfo["name"]
let age = userInfo["age"]
let address = userInfo["address"]
```
- 列出鍵和值:
```swift
let keys = userInfo.keys
let values = userInfo.values
```
- 遍歷鍵值對:
```swift
for (key, value) in userInfo {
print("\(key): \(value)")
}
```
## 其他
- **條件遍歷**:
```swift
for (key, value) in userInfo where value is Int {
print("\(key): \(value)")
}
```
- **多條件遍歷**:
```swift
for (key, value) in userInfo where value is Int && key.count > 2 {
print("\(key): \(value)")
}
```
## 小結
- **熟練使用集合**:理解和使用陣列、集合和字典是 Swift 開發的重要技能。
- **練習**:通過實踐熟悉各種操作和語法,增強對集合的掌握。
# Equality and Hashing 等值與雜湊
## 介紹
- **等值(Equality)**:判斷兩個對象是否相等。
- **雜湊(Hashing)**:確保對象在集合(Set)中唯一。
## Equatable Protocol
- **定義**:使對象可等值比較。
- **實現**:需實現一個靜態函數 `==`。
```swift
static func ==(lhs: Self, rhs: Self) -> Bool
```
## 自動生成 Equatable
- **結構體示例**:
```swift
struct Person: Equatable {
let id: String
let name: String
}
```
- **比較示例**:
```swift
let foo1 = Person(id: "1", name: "Foo")
let foo2 = Person(id: "1", name: "Bar")
if foo1 == foo2 {
print("They are equal")
} else {
print("They are not equal")
}
```
## 自定義 Equatable
- **自定義相等條件**:
```swift
extension Person {
static func ==(lhs: Person, rhs: Person) -> Bool {
return lhs.id == rhs.id
}
}
```
## 列舉(Enumeration)中的 Equatable
- **自動生成**:
```swift
enum AnimalType: Equatable {
case dog(breed: String)
case cat(breed: String)
}
```
- **自定義**:
```swift
extension AnimalType {
static func ==(lhs: AnimalType, rhs: AnimalType) -> Bool {
switch (lhs, rhs) {
case (.dog(let lhsBreed), .dog(let rhsBreed)):
return lhsBreed == rhsBreed
case (.cat(let lhsBreed), .cat(let rhsBreed)):
return lhsBreed == rhsBreed
default:
return false
}
}
}
```
## Hashable Protocol
- **定義**:使對象可雜湊,通常用於集合(Set)。
- **實現**:需實現 `hash(into:)` 方法。
```swift
func hash(into hasher: inout Hasher)
```
## 自動生成 Hashable
- **結構體示例**:
```swift
struct House: Hashable {
let number: Int
let numberOfBedrooms: Int
}
```
- **使用示例**:
```swift
let house1 = House(number: 123, numberOfBedrooms: 2)
let house2 = House(number: 123, numberOfBedrooms: 3)
print(house1.hashValue)
print(house2.hashValue)
```
## 自定義 Hashable
- **自定義雜湊條件**:
```swift
struct NumberedHouse: Hashable {
let number: Int
let numberOfBedrooms: Int
func hash(into hasher: inout Hasher) {
hasher.combine(number)
}
static func ==(lhs: NumberedHouse, rhs: NumberedHouse) -> Bool {
return lhs.number == rhs.number
}
}
```
## 列舉中的 Hashable
- **列舉示例**:
```swift
enum CarPart: Hashable {
case roof
case tire
case trunk
}
let uniqueParts: Set<CarPart> = [.roof, .tire, .roof, .trunk]
```
- **帶關聯值的列舉**:
```swift
enum HouseType: Hashable {
case bigHouse(NumberedHouse)
case smallHouse(NumberedHouse)
}
```
## 集合中的使用
- **示例**:
```swift
let bigHouse1 = HouseType.bigHouse(NumberedHouse(number: 1, numberOfBedrooms: 1))
let bigHouse2 = HouseType.bigHouse(NumberedHouse(number: 1, numberOfBedrooms: 1))
let smallHouse1 = HouseType.smallHouse(NumberedHouse(number: 1, numberOfBedrooms: 1))
let allHouses: Set<HouseType> = [bigHouse1, bigHouse2, smallHouse1]
print(allHouses.count) // Output: 2
```
## 小結
- **Equatable**:用於比較對象是否相等。
- **Hashable**:用於確保對象在集合中唯一。
- **自動生成 vs 自定義**:根據需要選擇使用 Swift 提供的自動生成或自定義實現。
- **實踐**:多練習以加深理解這些概念的應用。
# Custom Operators 自訂運算符
## 介紹
- **自訂運算符**:在 Swift 中可以創建自訂運算符以實現更直觀的操作。
- **運算符類型**:
- **二元中綴運算符(Binary Infix Operator)**
- **一元前綴運算符(Unary Prefix Operator)**
- **一元後綴運算符(Unary Postfix Operator)**
## 二元中綴運算符(Binary Infix Operator)
### 示例
- **示例:合併兩個可選字符串**
```swift
func +(lhs: String?, rhs: String?) -> String? {
switch (lhs, rhs) {
case (nil, nil):
return nil
case (let left?, nil):
return left
case (nil, let right?):
return right
case (let left?, let right?):
return left + right
}
}
let firstName: String? = "Foo"
let lastName: String? = "Bar"
let fullName = firstName + lastName // "FooBar"
```
## 一元前綴運算符(Unary Prefix Operator)
### 示例
- **示例:將字符串轉換為大寫**
```swift
prefix operator ^
prefix func ^(value: String) -> String {
return value.uppercased()
}
let lowercaseName = "foobar"
let uppercaseName = ^lowercaseName // "FOOBAR"
```
## 一元後綴運算符(Unary Postfix Operator)
### 示例
- **示例:在字符串前後添加星號**
```swift
postfix operator *
postfix func *(value: String) -> String {
return "*** \(value) ***"
}
let name = "foobar"
let starredName = name* // "*** foobar ***"
```
## 定義異類型的二元中綴運算符
### 示例
- **示例:合併 `Person` 和 `Family`**
```swift
struct Person {
let name: String
}
struct Family {
var members: [Person]
}
func +(lhs: Person, rhs: Person) -> Family {
return Family(members: [lhs, rhs])
}
func +(lhs: Family, rhs: Person) -> Family {
var members = lhs.members
members.append(rhs)
return Family(members: members)
}
func +(lhs: Family, rhs: [Person]) -> Family {
var members = lhs.members
members.append(contentsOf: rhs)
return Family(members: members)
}
let mom = Person(name: "Mom")
let dad = Person(name: "Dad")
let son = Person(name: "Son")
let daughter1 = Person(name: "Daughter1")
let daughter2 = Person(name: "Daughter2")
let family = mom + dad
let familyWithSon = family + son
let familyWithDaughters = familyWithSon + [daughter1, daughter2]
print(family.members.count) // 2
print(familyWithSon.members.count) // 3
print(familyWithDaughters.members.count) // 5
```
## 小結
- **創建自訂運算符**:
- **定義運算符**:使用 `prefix operator`、`postfix operator` 或直接定義二元運算符。
- **實現運算符**:根據需要實現對應的函數邏輯。
- **運用場景**:
- **增強可讀性**:使代碼更直觀。
- **簡化操作**:將常用的操作封裝為運算符。
# 非同步編程(Asynchronous Programming)
## 介紹
- **非同步編程**:允許函數在不立即返回結果的情況下執行。
- **適用於多種語言**:Swift、Dart、Python、Rust 等。
## 基本設定
- **必要匯入**:
```swift
import Foundation
import PlaygroundSupport
import Concurrency
```
- **保持 Playground 活躍**:
```swift
PlaygroundPage.current.needsIndefiniteExecution = true
```
## 基本範例
- **建立簡單的非同步函數**:
```swift
func calculateFullName(firstName: String, lastName: String) async -> String {
try? await Task.sleep(nanoseconds: 1_000_000_000) // 模擬延遲1秒
return "\(firstName) \(lastName)"
}
```
- **調用非同步函數**:
```swift
Task {
let result = await calculateFullName(firstName: "Foo", lastName: "Bar")
print(result) // 輸出 "Foo Bar"
}
```
## async let 語法
- **定義**:創建子任務,並行執行。
- **示例**:
```swift
async let result1 = calculateFullName(firstName: "Foo", lastName: "Bar")
let result = await result1
```
## 完整範例
### 示例:購買衣物
- **定義衣物類型**:
```swift
enum Clothes {
case socks, shirt, trousers
}
```
- **非同步購買函數**:
```swift
func buySocks() async throws -> Clothes {
try await Task.sleep(nanoseconds: 1_000_000_000)
return .socks
}
func buyShirt() async throws -> Clothes {
try await Task.sleep(nanoseconds: 1_000_000_000)
return .shirt
}
func buyTrousers() async throws -> Clothes {
try await Task.sleep(nanoseconds: 1_000_000_000)
return .trousers
}
```
- **建立集合結構**:
```swift
struct Ensemble: CustomDebugStringConvertible {
let clothes: [Clothes]
let totalPrice: Double
var debugDescription: String {
return "Clothes: \(clothes), Price: \(totalPrice)"
}
}
```
- **購買整套衣物的非同步函數**:
```swift
func buyWholeEnsemble() async throws -> Ensemble {
async let socks = buySocks()
async let shirt = buyShirt()
async let trousers = buyTrousers()
let ensemble = Ensemble(
clothes: [try await socks, try await shirt, try await trousers],
totalPrice: 200.0
)
return ensemble
}
```
- **調用並測試**:
```swift
Task {
do {
let ensemble = try await buyWholeEnsemble()
print("Ensemble: \(ensemble)")
} catch {
print("Error: \(error)")
}
}
```
## 其他注意事項
- **async let 限制**:只能在非同步閉包、非同步函數或任務內使用。
- **示例**:
```swift
func getFullName(delay: Duration, calculator: @escaping () async -> String) async -> String {
try? await Task.sleep(for: delay)
return await calculator()
}
Task {
async let name = { "Foo Bar" }
let result = await getFullName(delay: .seconds(1), calculator: name)
print(result) // "Foo Bar"
}
```
## 總結
- **Swift 非同步編程**:類似於其他語言(如 JavaScript、Dart 等)的 async 和 await 語法。
- **特點**:
- **async let**:創建子任務並行執行,但需手動 await。
- **注意異常處理**:使用 try 和 throws 處理異常。
---
# 關鍵字
- **Playground**:一個可以立即執行並顯示結果的 Swift 環境,方便測試和學習 Swift 語言。
- **Foundation**:一個 Swift 標準庫,包含基本的數據類型和集合等常用功能。
- **值類型 (Value Types)**:在賦值或傳遞時會創建一個副本的數據類型,如結構 (Structures) 和枚舉 (Enumerations)。
- **參考類型 (Reference Types)**:在賦值或傳遞時會傳遞引用而非副本的數據類型,如類 (Classes)。
- **陣列 (Arrays)**:有序的數據集合,可以用索引來存取元素。
- **可變性 (Mutability)**:變數或常數內部數據是否可以更改的屬性。
- **`NSMutArray`**:Objective-C 的可變數組類,允許動態修改數組內容。
- **`NSMutArray`**:Objective-C 的不可變數組類,內容不可修改。
- **內部可變性 (Internal Mutability)**:即使常數本身不可重新賦值,其內部數據仍可以改變。
- **運算子 (Operators)**:特定符號或關鍵字,用於執行操作,如加法、減法、比較等。
- **二元運算子 (Binary Infix Operators)**:操作兩個值的運算子,位於兩個操作數之間,如 `+`、`-`、`*`、`>` 等。
- **一元前置運算子 (Unary Prefix Operators)**:操作單一值的運算子,位於操作數之前,如否定運算子 `!`。
- **一元後置運算子 (Unary Postfix Operators)**:操作單一值的運算子,位於操作數之後,如強制解包運算子 `!`。
- **三元運算子 (Ternary Operator)**:操作三個部分的運算子,用於簡化條件表達式,格式為 `condition ? value_if_true : value_if_false`。
- **整數 (Integer)**:沒有小數部分的數字。
- **常數 (Constants)**:值在宣告後不能改變的變數,用 `let` 關鍵字宣告。
- **變數 (Variables)**:值在宣告後可以改變的變數,用 `var` 關鍵字宣告。
- **字串 (String)**:一連串的字符,用於表示文本。
- **條件運算 (Conditional Operation)**:根據條件判斷執行不同操作,如 `if` 語句。
- **陣列 (Array)**:有序的數據集合,可以存取多個值。
- **`if` 語句**:用於根據條件執行不同程式碼塊的語句。
- **`else` 語句**:與 `if` 語句搭配使用,當 `if` 條件不成立時執行的程式碼塊。
- **`else if` 語句**:在 `if` 語句後面,用於檢查另一個條件。
- **條件運算子 (Conditional Operator)**:用於比較和判斷條件是否為真的運算子,如 `==`、`>`、`<`。
- **邏輯運算子 (Logical Operator)**:用於連接多個條件的運算子,如 `&&`(AND)和 `||`(OR)。
- **比較運算子 (Comparison Operator)**:用於比較兩個值的運算子,如 `==`(等於)、`!=`(不等於)、`>`(大於)、`<`(小於)、`>=`(大於或等於)、`<=`(小於或等於)。
- **邏輯與 (Logical AND)**:用於檢查多個條件是否都為真的運算子,符號為 `&&`。
- **邏輯或 (Logical OR)**:用於檢查多個條件中是否至少有一個為真的運算子,符號為 `||`。
- **括號 (Parentheses)**:用於組織和優先處理運算子的語句。
- **變數內插 (String Interpolation)**:在字串中插入變數的值,用 `\()` 表示。
- **程式分支 (Program Branching)**:根據條件執行不同程式碼塊的流程控制。
- **函式 (Functions)**:一段可重複使用的程式碼,用於執行特定任務。
- **函式語法 (Function Syntax)**:使用 `func` 關鍵字定義函式,如 `func functionName() {}`。
- **駝峰命名法 (Camel Case)**:函式名稱的命名規則,第一個字母小寫,後續單詞的首字母大寫。
- **參數 (Parameters)**:傳遞給函式的輸入值,如 `func functionName(parameter: Type)`。
- **返回值 (Return Value)**:函式執行後返回的值,用箭頭 `->` 表示,如 `func functionName() -> ReturnType {}`。
- **引數 (Arguments)**:呼叫函式時傳入的具體值,如 `functionName(argument)`。
- **內部標籤 (Internal Label)**:函式內部使用的參數名稱,如 `func functionName(internalLabel: Type)`。
- **外部標籤 (External Label)**:函式外部使用的參數名稱,如 `func functionName(externalLabel internalLabel: Type)`。
- **無外部標籤 (No External Label)**:使用 `_` 來忽略參數的外部標籤,如 `func functionName(_ internalLabel: Type)`。
- **預設值 (Default Value)**:參數的預設值,讓函式可以在沒有提供該參數時使用預設值,如 `func functionName(parameter: Type = defaultValue)`。
- **內部函式 (Inner Function)**:定義在另一個函式內部的函式,只能在該外部函式內部調用。
- **可丟棄結果 (Discardable Result)**:標記函式的返回值可以被忽略,用 `@discardableResult` 標記。
- **閉包 (Closures)**:一種特殊的函式,可以捕獲並存取其所在範圍內的變數和常數。
- **閉包 (Closure)**:一種特殊的函式,可以捕獲並存取其所在範圍內的變數和常數,通常作為參數傳遞給其他函式使用。
- **內聯函式 (Inline Function)**:在程式碼中直接定義的函式,不使用 `func` 關鍵字。
- **函式參考 (Function Reference)**:將函式當作值來傳遞或指派給變數。
- **函式型別 (Function Type)**:定義函式接受的參數型別和返回值型別,如 `(Int, Int) -> Int`。
- **Trailing Closure 語法**:當閉包是函式的最後一個參數時,可以將閉包寫在函式呼叫的括號外面,使程式碼更易讀。
- **參數標籤 (Parameter Label)**:用於標識函式參數的名稱,可以是內部標籤(供函式內部使用)和外部標籤(供函式調用時使用)。
- **資料推斷 (Type Inference)**:編譯器自動推斷變數或閉包的型別,而不需要顯式指定。
- **無名參數 (Anonymous Parameters)**:使用 `$` 符號和索引號來引用參數,如 `$0` 代表第一個參數。
- **內嵌函式 (Nested Function)**:定義在另一個函式內部的函式,僅能在其外部函式內部調用。
- **預設參數值 (Default Parameter Value)**:當呼叫函式時未提供參數時使用的預設值。
- **外部標籤 (External Label)**:函式外部使用的參數標籤,用於呼叫函式時標識參數。
- **結構 (Struct)**:一種用來組織和封裝數據的資料結構,在 Swift 中是值類型。
- **屬性 (Property)**:結構內部的變數或常數,用於儲存結構的數據。
- **點標記法 (Dot Notation)**:用於存取結構屬性的方法,語法為 `instance.property`。
- **值類型 (Value Type)**:在賦值或傳遞時會創建一個副本的數據類型,如結構和枚舉。
- **自定初始化函式 (Custom Initializer)**:用來自定義結構實例的初始化邏輯的函式。
- **計算屬性 (Computed Property)**:一種屬性,實際上是一個函式,用於計算和返回一個值。
- **變異函式 (Mutating Function)**:可以修改結構內部屬性的函式,用 `mutating` 關鍵字標識。
- **自定複製函式 (Custom Copying Function)**:用於創建結構實例自定義副本的函式。
- **繼承 (Inheritance)**:一種允許一個類別從另一個類別獲取屬性和方法的功能,但結構不能繼承。
- **列舉 (Enumeration, Enum)**:一種數據類型,用來定義一組相關的值。每個值都是這個列舉類型的合法實例。
- **案例 (Case)**:列舉中的一個特定值。例如,`enum Animals { case cat, dog, rabbit }` 中的 `cat`、`dog` 和 `rabbit` 是列舉的案例。
- **點標記法 (Dot Notation)**:用來存取列舉案例的方法,例如 `Animals.cat`。
- **開關語句 (Switch Statement)**:用來比較列舉案例的一種控制流語句,能夠有效處理多個案例。
- **關聯值 (Associated Value)**:列舉案例可以攜帶的額外信息。例如 `case wwwURL(URL)` 中的 `URL` 是關聯值。
- **原始值 (Raw Value)**:列舉案例可以預設的值。例如 `enum FamilyMember: String { case father = "Dad", mother = "Mom" }`。
- **CaseIterable 協議**:一種協議,使列舉能夠返回所有案例的集合。
- **變異函式 (Mutating Function)**:可以修改列舉內部狀態的函式,用 `mutating` 關鍵字標識。
- **遞歸列舉 (Recursive Enumeration)**:列舉的一種形式,其中列舉案例可以包含其他列舉案例作為關聯值,需要用 `indirect` 關鍵字標識。
- **if case let 語句**:用來解包和比較列舉案例的語法,例如 `if case let .wwwURL(path) = instance`。
- **類別 (Class)**:一種複合數據類型,用來定義一組相關的屬性和方法。與結構不同,類別是引用類型(reference type)。
- **結構 (Struct)**:與類別相似,但它是值類型(value type),這意味著它們在賦值或傳遞時會進行複製。
- **引用類型 (Reference Type)**:當你將類別的實例賦值給另一個變數時,不會創建副本,而是將兩個變數指向同一個記憶體位置。
- **值類型 (Value Type)**:當你將結構的實例賦值給另一個變數時,會創建這個實例的副本。
- **初始化器 (Initializer)**:用來初始化類別或結構實例的方法,使用 `init` 關鍵字。
- **析構器 (Deinitializer)**:當類別實例被釋放時會調用的方法,使用 `deinit` 關鍵字。
- **指定初始化器 (Designated Initializer)**:負責初始化類別所有屬性的初始化器,不能調用其他初始化器。
- **便利初始化器 (Convenience Initializer)**:用來輔助指定初始化器的初始化器,最終需要調用指定初始化器來完成初始化。
- **繼承 (Inheritance)**:一個類別可以繼承另一個類別的屬性和方法,使得子類別擁有父類別的特性。
- **覆寫 (Override)**:子類別可以覆寫父類別的方法或屬性,使用 `override` 關鍵字。
- **變異方法 (Mutating Method)**:結構中的方法,允許修改實例屬性,使用 `mutating` 關鍵字,但類別中的方法不需要這個關鍵字。
- **私有設置 (Private Setter)**:允許屬性在類別內部被修改,但外部無法修改,使用 `private set` 關鍵字。
- **記憶體參照 (Memory Reference)**:當兩個變數指向同一個類別實例時,它們共享同一個記憶體位置。
- **協定 (Protocol)**:在 Swift 中,協定是一組方法和屬性的藍圖,任何符合該協定的類別、結構或列舉都必須實現這些方法和屬性。協定類似於其他語言中的接口(如 Java 中的 interfaces 或 Kotlin 中的 interfaces)。
- **函式宣告 (Function Declaration)**:在協定中僅定義函式的名稱、參數和返回值,而不實現其具體功能。
- **符合 (Conform)**:當一個類別、結構或列舉實現協定中定義的所有方法和屬性時,我們說它符合該協定。
- **擴展 (Extension)**:在 Swift 中,擴展用來為現有的類別、結構、列舉或協定添加新功能,而無需修改原始代碼。
- **默認實現 (Default Implementation)**:在協定的擴展中可以為協定中的方法提供默認實現,這樣符合協定的類別或結構就不必自己實現這些方法。
- **變異方法 (Mutating Method)**:允許結構或列舉中的方法在其內部修改屬性,使用 `mutating` 關鍵字來標示。
- **檢查類型 (Type Checking)**:使用 `is` 關鍵字來檢查某個實例是否符合某個協定或是否為某個類型。
- **類型轉換 (Type Casting)**:使用 `as` 或 `as?` 關鍵字來將一個類型轉換為另一個類型,`as?` 返回一個可選值。
- **任意類型 (Any)**:表示任何類型的實例,包括類別、結構、列舉等。
- **非可變類型 (Immutable Type)**:使用 `let` 關鍵字聲明的常量,一旦賦值後無法更改。
- **可變類型 (Mutable Type)**:使用 `var` 關鍵字聲明的變量,可以在賦值後進行修改。
- **擴展 (Extension)**:在 Swift 中,擴展用來為現有的類別、結構、列舉或協定添加新功能,而無需修改原始代碼。擴展可以添加屬性、方法和初始值設置器等。
- **自我 (Self)**:在擴展中的 `self` 指的是擴展目標的當前實例。例如,在擴展整數 (Int) 時,`self` 代表整數的實例。
- **初始值設置器 (Initializer)**:用於在創建類別或結構的實例時設置其初始值。擴展可以為現有的類別或結構添加新的初始值設置器。
- **便利初始值設置器 (Convenience Initializer)**:一種特殊的初始值設置器,它調用類別的其他設置器來完成實例初始化。在擴展中,可以添加便利初始值設置器來簡化某些初始化過程。
- **協定 (Protocol)**:定義一組方法和屬性的藍圖,任何符合該協定的類別、結構或列舉都必須實現這些方法和屬性。協定可以用擴展來添加默認實現。
- **遵循 (Conformance)**:當一個類別、結構或列舉實現協定中定義的所有方法和屬性時,我們說它遵循該協定。
- **計算屬性 (Computed Property)**:一種屬性,不直接存儲值,而是通過計算獲得值。在協定中可以定義計算屬性。
- **範型 (Generic)**:範型允許類別、結構、函式和協定根據它們使用的類型進行參數化,使其更具靈活性和重用性。範型通常用於定義容器類型(如陣列、字典)等。
- **選擇性 (Optionals)**:表示一個值可能存在也可能不存在。選擇性值可以是某種類型的實際值或 `nil`,表示缺少值。
- **解包 (Unwrapping)**:從選擇性中提取值的過程。使用 `if let` 或 `guard let` 可以安全地解包選擇性值。
- **可選鏈 (Optional Chaining)**:一種語法,用於在鏈式調用中安全地訪問選擇性屬性、方法或下標,即使中間有 `nil`。
- **無 (nil)**:表示缺少值,選擇性的默認值。相當於其他語言中的 `null` 或 `None`。
- **if let**:一種解包選擇性值的語法,用於檢查選擇性值是否存在,如果存在則執行代碼塊內的操作。
- **guard let**:類似於 `if let` 的語法,用於強制解包選擇性值,如果選擇性值為 `nil`,則立即退出當前範圍(通常是函數或循環)。
- **選擇性鏈 (Optional Chaining)**:允許對可能為 `nil` 的值進行安全的屬性、方法和下標訪問。如果中間任一節點為 `nil`,整個鏈式調用將返回 `nil`。
- **switch 語句 (Switch Statement)**:用於模式匹配和處理不同情況的控制結構。在選擇性上下文中,可以用於匹配 `nil` 或某個具體值。
- **模式匹配 (Pattern Matching)**:在 `switch` 語句中使用 `case` 和 `where` 子句進行更細緻的值匹配。
- **選擇性類型 (Optional Type)**:選擇性是 Swift 中的特定類型,由 `Optional` 枚舉實現,具有 `some` 和 `none` 兩個案例。
- **關聯類型 (Associated Type)**:用於在協定中指定泛型參數的一種方法。關聯類型允許協定使用佔位符來表示不同類型,這些類型在實現協定時會被具體化。
- **guard 語句 (Guard Statement)**:用於提前退出範圍的控制結構,當條件不滿足時,立即執行 `else` 子句並退出當前範圍。
- **可選鏈判斷 (Optional Binding)**:通過 `if let` 或 `guard let` 解包選擇性值並判斷其是否存在。
- **錯誤處理 (Error Handling)**:在程序中處理錯誤情況的技術。通過拋出(throwing)和捕捉(catching)錯誤來管理程式中的異常情況。
- **拋出(Throwing)**:當程序遇到錯誤情況時,用於產生一個錯誤。使用 `throw` 關鍵字。
- **捕捉(Catching)**:在程序中捕獲拋出的錯誤。通常使用 `do-catch` 語句來處理錯誤。
- **結果(Result)**:一種表示操作成功或失敗的類型。通常用於返回操作的成功結果或錯誤。
- **重拋出(Rethrows)**:用於表示一個函數會拋出錯誤,因為它內部調用了另一個可能會拋出錯誤的函數。
- **集合 (Collection)**:一組相關的數據,可以是數組(Array)、集合(Set)或字典(Dictionary)。集合中的數據可以通過不同的方法進行操作。
- **數組 (Array)**:一種有序集合,其中的元素可以是任何類型的數據。數組中的元素可以重複,並且是按索引(從零開始)排序的。
- **插入 (Insert)**:將新元素添加到數組中的特定位置。例如,`insert(contentsOf:at:)` 可以將整個數組插入到另一個數組中的特定位置。
- **列舉 (Enumerate)**:遍歷集合中的每個元素。可以使用 `for` 迴圈來遍歷數組或集合中的所有元素。
- **篩選 (Filter)**:從集合中選擇符合特定條件的元素。例如,`filter { $0 > 2 }` 會返回一個僅包含大於 2 的元素的數組。
- **映射 (Map)**:將集合中的每個元素轉換為另一個值,並返回包含這些新值的集合。例如,`map { $0 * 2 }` 將數組中的每個數字乘以 2。
- **壓縮映射 (Compact Map)**:類似於 `map`,但會自動移除結果中的 `nil` 值。例如,`compactMap { $0 }` 會返回一個不包含 `nil` 值的數組。
- **選擇性 (Optional)**:一種類型,表示值可能存在也可能不存在。可以使用 `if let` 或 `guard let` 解包選擇性值。
- **子腳本 (Subscript)**:通過索引或鍵來訪問集合中的元素。例如,`array[0]` 會返回數組的第一個元素,`dictionary["key"]` 會返回字典中對應鍵的值。
- **集合 (Set)**:一種無序集合,其中的元素是唯一的。集合中不允許有重複的元素。
- **字典 (Dictionary)**:一種無序集合,其中的元素是鍵值對。每個鍵都是唯一的,並且每個鍵對應一個值。
- **強制轉型 (Force Casting)**:使用 `as!` 來強制將一個對象轉換為特定類型。如果轉型失敗,會導致運行時錯誤。
- **鍵 (Key)**:在字典中,用於標識值的唯一標識符。
- **值 (Value)**:在字典中,與特定鍵相關聯的數據。
- **哈希表 (Hashable)**:一個協議,表示一個類型可以計算其哈希值。實現這個協議的類型可以用於集合和字典中。
- **相等性 (Equatable)**:一個協議,表示一個類型可以進行相等性比較。實現這個協議的類型可以使用 `==` 來比較兩個實例是否相等。
- **可比較協議 (Equatable protocol)**:Swift中的一個協議,任何符合這個協議的對象必須實現一個靜態方法`==`,該方法用於比較兩個對象是否相等。
- **靜態方法 (Static method)**:屬於類別或結構體本身的方法,而不是屬於具體實例的方法。在這裡,`==`方法是靜態方法。
- **結構體 (Struct)**:Swift中的一種數據類型,用於定義由多個屬性組成的對象。
- **自定義相等性 (Custom equality)**:自定義`==`方法以實現特定的相等性邏輯,而不是使用Swift提供的默認相等性比較。
- **列舉 (Enum)**:Swift中的一種數據類型,用於定義一組相關的值。
- **關聯值 (Associated values)**:列舉中的特定成員可以帶有的值。例如,`enum AnimalType`中的`case dog(breed: String)`。
- **哈希協議 (Hashable protocol)**:Swift中的一個協議,任何符合這個協議的對象必須能夠生成一個哈希值。這些對象可以存儲在集合(Set)或作為字典(Dictionary)的鍵。
- **哈希值 (Hash value)**:用於唯一標識對象的值。哈希值通常是整數,用於快速查找和比較對象。
- **覆寫哈希方法 (Override hash method)**:自定義`hash(into:)`方法,以實現特定的哈希邏輯。
- **覆寫相等性方法 (Override equality method)**:自定義`==`方法,以實現特定的相等性邏輯。
- **Set**:一種集合,只包含唯一的元素。元素不允許重複,且無序。
- **Dictionary**:一種鍵值對集合,每個鍵都是唯一的,用於快速查找對應的值。
- **集合的計數 (Count of a collection)**:集合中元素的數量。
- **列舉的原始值 (Raw value of an enum)**:列舉成員的具體值。這些值可以是整數、字符串或其他數據類型。
- **模式匹配 (Pattern matching)**:一種匹配結構和枚舉成員的技術,用於確定數據是否符合某種模式。
- **自定義運算符 (Custom Operators)**:在 Swift 中,自定義運算符允許開發者定義新的運算符或重新定義現有運算符,以處理特定類型之間的操作。
- **二元中置運算符 (Binary Infix Operator)**:一種運算符,放置在兩個操作數之間,並對這兩個操作數進行操作,例如 `a + b` 中的 `+`。
- **單元前置運算符 (Unary Prefix Operator)**:一種運算符,放置在單個操作數之前,並對該操作數進行操作,例如 `-a` 中的 `-`。
- **單元後置運算符 (Unary Postfix Operator)**:一種運算符,放置在單個操作數之後,並對該操作數進行操作,例如 `a!` 中的 `!`。
- **運算符聲明 (Operator Declaration)**:定義一個新的運算符並指定它是前置、後置或中置運算符,例如 `prefix operator ^^` 或 `infix operator **`。
- **運算符實現 (Operator Implementation)**:為自定義運算符定義具體行為的函數,例如 `func + (left: String?, right: String?) -> String?`。
- **可選 (Optional)**:一種可以包含值或 nil 的類型,表示值可能缺失。
- **函數重載 (Function Overloading)**:定義多個同名函數,但這些函數的參數類型或數量不同。
- **成員 (Member)**:在結構體或類中的屬性或方法,例如 `struct Person { let name: String }` 中的 `name`。
- **追加 (Append)**:在集合或數組中添加新元素的方法,例如 `array.append(element)`。
- **並發 (Concurrency)**:同時執行多個計算任務,以提高程序的效率和性能。Swift 支援並發編程,使得在不同線程上執行任務變得更加容易。
- **異步 (Asynchronous)**:一種編程模式,允許函數在不阻塞當前執行線程的情況下進行操作,並在操作完成後返回結果。異步函數通常會在背景線程中執行任務。
- **函數 (Function)**:一個可重用的代碼塊,通過名稱進行調用。函數可以接受參數並返回結果。
- **異步函數 (Async Function)**:使用 `async` 關鍵字標記的函數,表示該函數是異步的,可以在不阻塞當前線程的情況下執行任務。
- **等待 (Await)**:使用 `await` 關鍵字等待異步操作完成並獲取其結果。在 Swift 中,`await` 關鍵字僅能在異步函數或異步上下文中使用。
- **任務 (Task)**:表示一個並發執行的工作單元。在 Swift 中,可以使用 `Task` 初始化器來創建並執行一個異步任務。
- **異步讓 (Async Let)**:用於創建子任務並並行運行。使用 `async let` 來聲明並啟動一個異步操作。
- **嘗試 (Try)**:用於捕獲和處理異常。當調用可能會拋出異常的函數時,需要使用 `try` 關鍵字。在異步上下文中,通常會與 `await` 結合使用。
- **睡眠 (Sleep)**:暫停當前線程的執行一段時間。在 Swift 中,`Task.sleep` 函數用於異步地暫停當前任務。
- **結構體 (Struct)**:一種值類型,用於定義一組相關的屬性和方法。結構體是 Swift 中的一種重要數據類型。
- **列舉 (Enum)**:用於定義一組相關的值。每個列舉值都是該列舉類型的一個實例。
- **協議 (Protocol)**:定義了一組方法和屬性,其他類型可以採用這些協議來實現相應的行為。
- **調試字符串可轉換 (Custom Debug String Convertible)**:一個協議,用於定義自定義類型在調試時的描述方式。
- **主循環 (Main Loop)**:應用程序的主要運行循環,負責處理事件和調度任務。在需要長時間運行的異步操作中,需要確保主循環持續運行。