From f03cc68c0d2819e7f8d02c40ca138255465f5f2c Mon Sep 17 00:00:00 2001 From: Zhang Date: Mon, 11 Nov 2024 19:22:25 +0800 Subject: [PATCH] doc: update docs/swift.md (#850) --- docs/swift.md | 274 +++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 247 insertions(+), 27 deletions(-) diff --git a/docs/swift.md b/docs/swift.md index 859d2979a37..5780da551be 100644 --- a/docs/swift.md +++ b/docs/swift.md @@ -521,6 +521,10 @@ let zeroToThree = 0...3 // zeroToThree: 0, 1, 2, 3 ``` +- `a...b` 闭区间 (Closed Range) 包括a和b +- `a..(repeating: 0, count: 3) +print(sizes) // 打印: [0, 0, 0] +``` + ### .append() 方法和 += 运算符 ```swift @@ -1077,7 +1091,7 @@ func convertFracToDec(numerator: Double, denominator: Double) -> Double { } let decimal = convertFracToDec(numerator: 1.0, denominator: 2.0) -print(decimal) // Prints: 0.5 +print(decimal) // 打印: 0.5 ``` ### 省略参数标签 @@ -1691,6 +1705,22 @@ currentTraffic.reportAccident() 扩展 --- +### 什么是扩展 + +扩展是向现有的类、结构体、枚举或协议类型添加新功能的方法。包括添加新的方法、属性、初始化方法等。 + +### 为什么要使用扩展 + +扩展让开发者可以以一种非侵入的方式来增强类型的功能,当我们无法直接修改原始类或结构体时(例如,系统库的类),扩展允许我们在不改变原始源代码的情况下添加新功能。 + +### 基础语法 + +```swift +extension SomeType { + // 添加新功能 +} +``` + ### 声明扩展 ```swift @@ -1707,6 +1737,34 @@ extension Person: SomeProtocol { } ``` +### 扩展计算属性 + +```swift +// 扩展可以添加计算属性,不能添加存储属性 +extension Double { + var km: Double { self * 1000 } + var m: Double { self } + var cm: Double { self / 100.0 } + var mm: Double { self / 1000.0 } +} +let metric: Double = 30.48.cm +print("1 metric is \(metric.m) meter") +print("1 metric is \(metric.km) kilometer") +``` + +### 扩展可变实例方法 + +```swift +extension Double { + mutating func cube() { + self = self * self * self + } +} +var boxCube: Double = 2.0 +boxCube.cube() +print(boxCube) +``` + ### 扩展构造器 @@ -1726,19 +1784,50 @@ let frame = CGRect(center: CGPoint(x: 100, y: 100), print("Origin is \(frame.origin)") ``` -### 扩展可变实例方法 +### 扩展协议 + + + +它的工作方式与抽象类类似,适用于在所有实现某种协议的类中提供某些功能的情况(而不需要从一个公共的基类继承)。 ```swift -extension Double { - mutating func cube() { - self = self * self * self +// 定义协议 +protocol Drawable { + func draw() +} + +// 使用协议扩展为 draw 方法提供默认实现 +extension Drawable { + func draw() { + print("绘制形状") } } -var boxCube: Double = 2.0 -boxCube.cube() -print(boxCube) + +// 定义一个符合 Drawable 协议的类 Circle +class Circle: Drawable { + // Circle 可以使用默认的 draw 实现 + // 或者覆盖它 +} + +// 定义另一个符合 Drawable 协议的类 Square +class Square: Drawable { + // 重写 draw 方法以提供自定义实现 + func draw() { + print("画一个正方形") + } +} + +// 使用示例 +let circle = Circle() +circle.draw() // 打印: 绘制形状 + +let square = Square() +square.draw() // 打印: 画一个正方形 + ``` +你可以使用协议扩展来给协议的任意方法或者计算属性要求提供默认实现。如果遵循类型给这个协议的要求提供了它自己的实现,那么它就会替代扩展中提供的默认实现。 + ### 扩展方法 @@ -1755,21 +1844,6 @@ extension String { print("Hello World".deletingPrefix("He")) ``` -### 扩展计算属性 - -```swift -// 扩展可以添加计算属性,不能添加存储属性 -extension Double { - var km: Double { self * 1000 } - var m: Double { self } - var cm: Double { self / 100.0 } - var mm: Double { self / 1000.0 } -} -let metric: Double = 30.48.cm -print("1 metric is \(metric.m) meter") -print("1 metric is \(metric.km) kilometer") -``` - ### 扩展存储属性 @@ -1789,6 +1863,152 @@ extension UIColor { } ``` +泛型 +--- + +### 什么是泛型 + +在Swift中,泛型是一个允许我们创建可以使用任何数据类型的函数、类、结构和协议的特性。 + +### 为什么使用泛型 + +泛型使我们能够编写清晰简洁的代码,并能够与任何数据类型一起工作。通过使用占位符(如 `T`),可以减少引入错误的风险。 + +### 泛型函数 + + +```swift +// 接受两个类型相同的参数并交换它们 +func swapTwoValues(_ a: inout T, _ b: inout T) { + let temp = a + a = b + b = temp +} + +var a = 10 +var b = 20 +swapTwoValues(&a, &b) +print(a) // 打印: 20 +print(b) // 打印: 10 + +var c = "Hello" +var d = "World" +swapTwoValues(&c, &d) +print(c) // 打印: "World" +print(d) // 打印: "Hello" +``` + +### 基础用法 + +```swift +func foo(a: T, b: U) { + // ... +} + +struct Foo { + var a: T + // ... +} +``` + +在这个例子中,`T`和`U`是一个类型占位符,它表示任何类型,写在尖括号内(如``) + +### 泛型结构体 + +```swift +// 定义一个泛型结构体 Box +// 它有一个名为 value 的泛型属性 +struct Box { + var value: T +} + +let intBox = Box(value: 10) +let stringBox = Box(value: "Hello") + +print(intBox.value) // 打印: 10 +print(stringBox.value) // 打印: "Hello" +``` + +### 泛型约束 + +有时我们希望限制泛型的类型范围,可以使用泛型约束。比如,限制泛型类型必须是遵循某个协议的类型 + +```swift +struct Box { + var value: T + + // 计算 value 的平方函数 + func square() -> T { + return value * value + } +} + +let intBox = Box(value: 10) +print(intBox.square()) // 输出 100 + +let floatBox = Box(value: 5.0) +print(floatBox.square()) // 输出 25.0 + +// 以下代码会报错,因为String不遵循Numeric协议 +// let stringBox = Box(value: "Hello") +``` + +### 泛型类型别名 + + + +为泛型类型创建别名`typealias`,这样可以给泛型类型起一个更具体的名字,使得代码更加清晰易懂 + +- 示例1 + +```swift +// 定义一个泛型类型别名 'IntBox' +typealias IntBox = Box + +// 使用类型别名创建一个存储 Int 类型值的 Box 实例 +let intBox = IntBox(value: 42) +print(intBox.value) // 输出 42 + +``` + +- 示例2 + +```swift +// 定义一个泛型类型别名 'StringBox',其中 T 被约束为 String +typealias StringBox = Box where T: StringProtocol + +// 使用类型别名创建一个存储 String 类型值的 Box 实例 +let stringBox = StringBox(value: "Hello, world!") +print(stringBox.value) // 输出 "Hello, world!" +``` + +### 泛型协议 + +```swift +protocol Storage { + associatedtype Item + func store(item: Item) + func retrieve() -> Item? +} + +class SimpleStorage: Storage { + private var items: [T] = [] + + func store(item: T) { + items.append(item) + } + + func retrieve() -> T? { + return items.isEmpty ? nil : items.removeLast() + } +} + +let intStorage = SimpleStorage() +intStorage.store(item: 42) +print(intStorage.retrieve() ?? "Empty") +// 打印: 42 +``` + 另见 ----