Swift

函数

从基础的参数标签到 Swift 6 的类型化抛出和所有权控制,Swift 函数的设计始终贯穿着“清晰”与“安全”的理念。掌握这些特性,不仅能写出优雅的代码,更能从底层优化应用的性能与稳定性。

函数是 Swift 代码构建的基石。从简洁的闭包语法到 Swift 6 引入的严格并发检查,Swift 函数的功能日益强大。本文将带你系统回顾 Swift 函数的核心特性,并深入解析 Swift 6 带来的重大更新。

基础语法 (Basics)

定义与调用

Swift 函数使用 func 关键字定义。函数可以接受参数并返回结果。

func greet(person: String) -> String {
    return "Hello, \(person)!"
}
print(greet(person: "World"))

参数标签与默认值

参数标签(Argument Labels)让函数调用更像自然语言。你可以指定外部标签和内部名称,或者使用 _ 省略外部标签。

func sayHello(to name: String, from sender: String = "Anonymous") {
    print("Hello \(name), from \(sender)")
}
sayHello(to: "Alice") // 使用默认值

隐式返回

如果函数体只有一行表达式,可以省略 return 关键字。

func add(_ a: Int, _ b: Int) -> Int {
    a + b
}

参数进阶 (Advanced Parameters)

可变参数 (Variadic Parameters)

使用 ... 表示参数可以接受零个或多个值,在函数内部作为数组处理。

func sum(_ numbers: Int...) -> Int {
    numbers.reduce(0, +)
}
sum(1, 2, 3, 4) // 10

输入输出参数 (In-Out Parameters)

默认情况下参数是常量的。使用 inout 关键字可以在函数内部修改参数值,并将修改同步回调用方。

func swapTwoInts(_ a: inout Int, _ b: inout Int) {
    let temporaryA = a
    a = b
    b = temporaryA
}
var x = 1, y = 2
swapTwoInts(&x, &y)

函数类型 (Function Types)

函数本身也是一种类型,可以作为参数传递,也可以作为返回值。

作为参数和返回值

func performOperation(_ mathFunction: (Int, Int) -> Int, _ a: Int, _ b: Int) -> Int {
    mathFunction(a, b)
}

嵌套函数 (Nested Functions)

函数可以定义在另一个函数内部,嵌套函数可以访问外部函数的变量。

func chooseStepFunction(backward: Bool) -> (Int) -> Int {
    func stepForward(input: Int) -> Int { input + 1 }
    func stepBackward(input: Int) -> Int { input - 1 }
    return backward ? stepBackward : stepForward
}

Swift 6 新特性:类型化抛出 (Typed Throws)

在 Swift 6 之前,抛出的错误被擦除为 any Error。Swift 6 允许明确指定错误类型,提高类型安全性和性能。

enum FileError: Error {
    case notFound
    case permissionDenied
}

// 明确抛出 FileError
func readFile(at path: String) throws(FileError) -> String {
    guard path.hasPrefix("/") else { throw .permissionDenied }
    return "Content"
}

调用时,catch 块中的 error 会自动推断为 FileError

Swift 6 新特性:所有权控制 (Ownership)

Swift 6 引入了系统级的内存管理控制,减少不必要的复制。

borrowing (借用)

borrowing 参数允许函数读取值但没有所有权,保证零拷贝且不可修改。

func readData(_ data: borrowing LargeStruct) {
    // 只读访问,无引用计数开销
}

consuming (消耗)

consuming 参数将所有权转移给函数。函数结束时,值被销毁或转移。

func saveData(_ data: consuming LargeStruct) {
    // data 所有权已转移,调用方无法再使用
    database.store(data)
}

并发与隔离 (Concurrency & Isolation)

async / await

定义异步函数,使异步代码像同步代码一样清晰。

func fetchData() async throws -> Data {
    let (data, _) = try await URLSession.shared.data(from: url)
    return data
}

isolated 参数

将函数绑定到特定的 Actor 隔离域。

func updateUI(on actor: isolated MainActor) {
    // 自动在 MainActor 上下文中执行
}

@Sendable

标记函数或闭包为并发安全,可跨隔离域传递。

let task = Task { @Sendable in
    // 并发安全的操作
}

其他实用特性

@discardableResult

允许调用方忽略返回值而不产生警告。

@discardableResult
func log(_ message: String) -> Bool {
    print(message)
    return true
}

opaque vs existential return types

  • some View: 不透明类型,返回确定的单一类型,性能更好。
  • any View: 存在类型,可以动态返回不同类型,但在 Swift 6 中会有更多显式开销。

总结

从基础的参数标签到 Swift 6 的类型化抛出和所有权控制,Swift 函数的设计始终贯穿着“清晰”与“安全”的理念。掌握这些特性,不仅能写出优雅的代码,更能从底层优化应用的性能与稳定性。

在 GitHub 上编辑

上次更新于