Swift

控制流

解析 Swift 控制流机制,涵盖基础的条件与循环语句,以及 Swift 5.9+ 引入的 if/switch 表达式、Swift 6 的类型化错误处理与并发控制流。

控制流是程序的骨架,决定了代码的执行路径。Swift 提供了丰富且现代的控制流机制,从基础的分支循环到强大的模式匹配,再到 Swift 6 引入的并发控制增强,每一项特性都旨在提高代码的安全性和表达力。

条件语句 (Conditionals)

if 和 switch 表达式

从 Swift 5.9 开始,ifswitch 可以作为表达式使用,直接返回值。这使得代码更加简洁,特别是在变量赋值时。

let score = 85
let grade = if score >= 90 { "A" }
            else if score >= 80 { "B" }
            else { "C" }
// grade 为 "B"

switch 的强大匹配

Swift 的 switch 必须是完备的(exhaustive),且支持元组、区间和类型匹配。

let point = (1, 1)
switch point {
case (0, 0):
    print("Origin")
case (_, 0):
    print("On X-axis")
case (-2...2, -2...2):
    print("Inside box")
default:
    print("Outside")
}

guard 提前退出

guard 语句用于确保前置条件成立,否则提前退出当前作用域。它强制在 else 块中使用 returnthrowbreak,避免了嵌套的 if-let 金字塔。

func process(user: [String: String]) {
    guard let name = user["name"] else { return }
    print("Hello, \(name)")
}

循环 (Loops)

for-in

最常用的循环,用于遍历序列(如数组、范围)。

for index in 1...5 {
    print(index)
}

// 遍历字典
for (key, value) in ["a": 1, "b": 2] {
    print("\(key): \(value)")
}

while 和 repeat-while

while 先判断后执行,repeat-while 先执行后判断(至少执行一次)。

var count = 3
repeat {
    print(count)
    count -= 1
} while count > 0

控制转移 (Control Transfer)

defer 延时执行

defer 代码块会在当前作用域退出前执行,无论是因为 returnthrow 还是正常结束。常用于资源清理。

func openFile() {
    print("Opening file")
    defer { print("Closing file") }
    
    // 处理文件...
    if true { return } 
    // 输出顺序: Opening file -> Closing file
}

注意:多个 defer 块按后进先出 (LIFO) 的顺序执行。

模式匹配 (Pattern Matching)

Swift 的控制流与模式匹配深度结合。

值绑定与 where 子句

let data: (Int, String) = (200, "OK")
switch data {
case (200, let message):
    print("Success: \(message)")
case let (code, _) where code >= 400:
    print("Error: \(code)")
default:
    break
}

错误处理流 (Error Handling Flow)

do-catch 与类型化抛出 (Swift 6)

Swift 6 引入了类型化抛出(Typed Throws),使得 catch 块能自动推断具体的错误类型。

enum NetworkError: Error {
    case timeout
}

func fetch() throws(NetworkError) {
    throw .timeout
}

do {
    try fetch()
} catch {
    // error 在此被推断为 NetworkError 类型
    print(error == .timeout ? "Timed out" : "Unknown")
}

并发控制流 (Concurrency Flow)

await 与挂起

在异步函数中,await 标记了潜在的挂起带(Suspension Point)。程序执行到此处可能会暂停,释放线程去处理其他任务,待异步操作完成后恢复。

func loadData() async throws {
    print("Start")
    let data = try await URLSession.shared.data(from: url) // 挂起点
    print("Loaded \(data.count) bytes")
}

async let 结构化并发

async let 允许并发执行子任务,并在需要结果时等待。

async let image1 = downloadImage("1.jpg")
async let image2 = downloadImage("2.jpg")
// 并发下载,此处等待两者完成
let images = try await [image1, image2]

总结

Swift 的控制流设计兼顾了清晰性与安全性。从基础的 guard 卫语句到现代的 if 表达式,再到 Swift 6 的类型化错误处理,掌握这些工具能让你写出逻辑严密、易于维护的高质量代码。

在 GitHub 上编辑

上次更新于