Swift 函数完全指南(一)——从入门到嵌套

函数的本质

  1. 自包含的代码片段,完成一个"任务"。
  2. 有名字 → 可被重复"调用"。
  3. 有类型 → 由"参数类型 + 返回类型"组成,可以像 Int、String 一样被赋值、传递、返回
  4. 可嵌套 → 在函数内部再定义函数,实现隐藏实现细节。

语法骨架速记

swift 复制代码
func 函数名(参数列表) -> 返回类型 {
    // 函数体
}

调用:

函数名(实参)

知识点全景图

无参函数

swift 复制代码
// 无输入、无输出(返回 Void)
func sayHelloWorld() {
    print("hello, world")
}
sayHelloWorld()

易错点:调用时也必须写空括号 (),否则编译器会当成"函数引用"而非"调用"。

单参 + 单返回值

swift 复制代码
func greet(person: String) -> String {
    // 字符串插值更 Swifty
    return "Hello, \(person)!"
}
print(greet(person: "Anna"))   // Hello, Anna!

简化写法:单表达式可省 return

swift 复制代码
func greetAgain(person: String) -> String {
    "Hello again, \(person)!"   // 隐式返回
}

多参数

swift 复制代码
func greet(person: String, alreadyGreeted: Bool) -> String {
    alreadyGreeted ? greetAgain(person: person) : greet(person: person)
}
print(greet(person: "Tim", alreadyGreeted: true))

注意:函数名相同但参数列表不同 → 函数重载(Swift 支持)。

无返回值

swift 复制代码
func greet(person: String) {
    print("Hello, \(person)!")
}

细节:

  • 不写 -> Void 与写 -> Void 完全等价。
  • 调用者可使用 _ = 显式忽略返回值,提高代码可读性。

多返回值 → 元组(Tuple)

swift 复制代码
func minMax(array: [Int]) -> (min: Int, max: Int) {
    var curMin = array[0], curMax = array[0]
    for value in array.dropFirst() {
        if value < curMin { curMin = value }
        if value > curMax { curMax = value }
    }
    return (curMin, curMax)
}
let bounds = minMax(array: [8, -6, 2, 109])
print("最小 \(bounds.min) 最大 \(bounds.max)")

可选元组:当数组可能为空时,返回整个元组为 nil

swift 复制代码
func minMaxSafe(array: [Int]) -> (min: Int, max: Int)? {
    guard !array.isEmpty else { return nil }
    ...
}

参数标签(Argument Label)与参数名

swift 复制代码
func greet(person: String, from hometown: String) -> String {
    "Hello \(person), glad you could visit from \(hometown)."
}
// 调用时形成"句子"
print(greet(person: "Bill", from: "Cupertino"))

省略标签:用 _

swift 复制代码
func add(_ a: Int, _ b: Int) -> Int { a + b }
add(2, 3)   // 不再强制写标签

默认参数值

swift 复制代码
func power(_ base: Int, _ exponent: Int = 2) -> Int {
    return (0..<exponent).reduce(1) { partialResult, _ in
        partialResult * base
    }
}
print(power(5))        // 25
print(power(5, 3))     // 125

规则:带默认值的参数放最右边;调用时省略就从右往左省略。

可变参数(Variadic Parameter)

swift 复制代码
func arithmeticMean(_ numbers: Double...) -> Double {
    guard !numbers.isEmpty else { return .nan }
    return numbers.reduce(0, +) / Double(numbers.count)
}
print(arithmeticMean(1, 2, 3, 4, 5))   // 3.0

限制:

  1. 一个函数可以有多个可变参,多个可变参只能有一个可以省略标签,其他的需要使用标签传递实参
  2. 若后面还有参数,必须带标签。

多个可变参

swift 复制代码
func arithmeticMean(_ numbers: Double..., names: String...) -> Double {
    guard !numbers.isEmpty else { return .nan }
    print(names)
    return numbers.reduce(0, +) / Double(numbers.count)
}
print(arithmeticMean(1, 2, 3, 4, 5, names:"a","b"))   // 3.0

in-out 参数:函数内部修改外部变量

swift 复制代码
func swapTwoInts(_ a: inout Int, _ b: inout Int) {
    (a, b) = (b, a)   // 元组交换,无需临时变量
}
var x = 3, y = 107
swapTwoInts(&x, &y)   // 调用时加 &
print("x=\(x) y=\(y)") // x=107 y=3

注意:

  • 只能传变量(var),不能传 let 常量或字面量。
  • in-out 与并发不兼容,不能跨 actor 使用。

函数类型:一等公民

swift 复制代码
typealias MathOp = (Int, Int) -> Int
let op: MathOp = (+)   // 系统运算符也是函数
print(op(2,3))         // 5

高阶函数实战:把函数当参数/返回值

swift 复制代码
func printResult(_ f: (Int,Int)->Int, _ a: Int, _ b: Int) {
    print("结果=\(f(a,b))")
}
printResult(+, 4, 5)

返回函数 → 工厂函数

swift 复制代码
func chooseStepFunction(backward: Bool) -> (Int) -> Int {
    backward ? { $0 - 1 } : { $0 + 1 }
}
var value = 3
let move = chooseStepFunction(backward: value > 0)
while value != 0 {
    print(value)
    value = move(value)
}

利用闭包简写,省掉嵌套函数写法,但逻辑等价。

嵌套函数(Nested Function)

swift 复制代码
func chooseStepNested(backward: Bool) -> (Int) -> Int {
    func stepForward(i: Int) -> Int { i + 1 }
    func stepBackward(i: Int) -> Int { i - 1 }
    return backward ? stepBackward : stepForward
}

特点:

  • 默认对外部不可见,封装更彻底。
  • 可捕获外层函数的局部变量(闭包特性)。

思维导图(文字版)

text 复制代码
函数
├─ 定义与调用
├─ 参数
│  ├─ 无参 / 多参
│  ├─ 标签与省略
│  ├─ 默认值
│  ├─ 可变参
│  └─ in-out
├─ 返回值
│  ├─ 无返回
│  ├─ 单值
│  ├─ 多值(元组)
│  └─ 可选元组
├─ 函数类型
│  ├─ 作为变量
│  ├─ 作为参数
│  └─ 作为返回值
└─ 嵌套函数

总结与实战建议

  1. 把"函数类型"真正当成类型:

    写网络层时,可把 (Data) -> Void 的回调类型 typealiasCompletion,一处修改处处生效。

  2. 默认参数 + 可变参组合:

    封装日志库时,func log(_ items: Any..., separator: String = " ") 既能接收任意数量,又能自定义分隔符。

  3. in-out 的替代方案:

    多数场景可用返回元组代替,语义更清晰;in-out 仅当"必须原地修改"且"性能敏感"才用。

  4. 嵌套函数是"小范围私有函数"的最佳实践:

    避免全局命名空间污染,尤其在算法题或表格视图控制器里,可把"工具函数"直接嵌套在 viewDidLoad 里。

  5. 函数式思维:

    多利用"函数作为返回值"做策略模式,比传统面向对象的"策略类"更轻量。例如根据用户配置返回不同价格计算器:

swift 复制代码
enum VipLevel { case normal, silver, gold }
func discount(for level: VipLevel) -> (Double) -> Double {
    switch level {
    case .normal:  { $0 }          // 无折扣
    case .silver:  { $0 * 0.9 }    // 9 折
    case .gold:    { $0 * 0.8 }    // 8 折
    }
}
let finalPrice = discount(for: .gold)(100) // 80
相关推荐
jh_cao15 小时前
(4)SwiftUI 基础(第四篇)
ios·swiftui·swift
progalchemist1 天前
Quick SwiftObjective-C测试框架入门教程
开发语言·其他·objective-c·swift
HarderCoder1 天前
Swift 闭包(Closure)从入门到深入:语法、捕获与实战
swift
HarderCoder1 天前
Swift 集合类型详解(三):自定义集合、持久化结构与 ORM 共舞
swift
HarderCoder1 天前
Swift 集合类型详解(一):Array、Set、Dictionary 全貌与选型思路
swift
HarderCoder1 天前
Swift 集合类型详解(二):自定义 Hashable、值语义与性能陷阱
swift
东坡肘子2 天前
Sora 2:好模型,但未必是好生意 | 肘子的 Swift 周报 #0105
人工智能·swiftui·swift
HarderCoder2 天前
Swift 6 并发深渊:@unchecked Sendable 与“隐式 MainActor”如何合谋杀死你的 App
swiftui·swift
HarderCoder2 天前
告别 UIKit 生命周期:SwiftUI 视图一生全解析——从 init 到 deinit 的“隐秘角落”
swiftui·swift