Swift 函数(Functions)全解析(2025 版)
“函数是一等公民” —— 掌握 参数、返回值、闭包、高阶函数、inout、@escaping,写出 优雅、灵活、高性能 的 Swift 代码!
一、函数核心概念
| 特性 | 说明 |
|---|---|
| 一等公民 | 可赋值、传参、返回 |
| 类型安全 | 参数和返回值有明确类型 |
| 默认参数 | 支持默认值 |
| 可变参数 | ... 接收多个值 |
| 返回值 | 支持 Void、Optional、元组 |
func greet(name: String) -> String {
return "Hello, \(name)!"
}
二、基本语法
1. 无参数无返回值
func sayHello() {
print("Hello!")
}
sayHello()
2. 有参数有返回值
func add(_ a: Int, _ b: Int) -> Int {
return a + b
}
let sum = add(3, 4) // 7
3. 多返回值(元组)
func minMax(_ numbers: [Int]) -> (min: Int, max: Int)? {
guard !numbers.isEmpty else { return nil }
return (numbers.min()!, numbers.max()!)
}
if let result = minMax([3, 1, 4]) {
print("最小:\(result.min), 最大:\(result.max)")
}
三、参数标签(Argument Labels)
// 完整写法
func move(from start: String, to end: String) {
print("从 \(start) 移动到 \(end)")
}
move(from: "北京", to: "上海")
// 省略标签
func add(_ a: Int, _ b: Int) -> Int { a + b }
// 默认值
func greet(name: String, greeting: String = "Hello") {
print("\(greeting), \(name)!")
}
greet(name: "小明") // Hello, 小明!
四、可变参数(Variadic Parameters)
func sum(_ numbers: Int...) -> Int {
return numbers.reduce(0, +)
}
print(sum(1, 2, 3, 4, 5)) // 15
限制:一个函数只能有一个可变参数,且必须在最后
五、inout 参数(传入传出)
修改外部变量
func increment(_ value: inout Int) {
value += 1
}
var x = 10
increment(&x) // 必须加 &
print(x) // 11
适用场景
- 交换两个值
- 修改结构体属性
- 避免返回新值
func swap(_ a: inout Int, _ b: inout Int) {
(a, b) = (b, a)
}
六、函数类型(Function Type)
// 类型:(Int, Int) -> Int
let mathFunc: (Int, Int) -> Int = add
// 使用
print(mathFunc(5, 3)) // 8
函数作为参数(高阶函数)
func apply(_ a: Int, _ b: Int, operation: (Int, Int) -> Int) -> Int {
return operation(a, b)
}
let result = apply(10, 5) { $0 * $1 } // 50
七、函数作为返回值
func makeCounter() -> () -> Int {
var count = 0
return {
count += 1
return count
}
}
let counter = makeCounter()
print(counter()) // 1
print(counter()) // 2
八、嵌套函数(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
}
let step = chooseStepFunction(backward: true)
print(step(10)) // 9
九、@escaping 闭包
闭包逃逸:函数返回后仍被调用
class NetworkManager {
var completionHandlers: [() -> Void] = []
func fetchData(completion: @escaping () -> Void) {
completionHandlers.append(completion)
// 模拟异步
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
completion()
}
}
}
不加 @escaping:编译错误(闭包被存储)
十、autoclosure(自动闭包)
延迟执行,简化语法
func log(if condition: @autoclosure () -> Bool) {
if condition() {
print("条件为真")
}
}
log(if 2 > 1) // 不用写 { 2 > 1 }
十一、throws 函数(错误处理)
enum MathError: Error {
case divisionByZero
}
func divide(_ a: Double, _ b: Double) throws -> Double {
guard b != 0 else { throw MathError.divisionByZero }
return a / b
}
// 调用
do {
let result = try divide(10, 0)
} catch {
print("错误:\(error)")
}
十二、函数重载(Overloading)
func print(_ value: Int) { print("Int: \(value)") }
func print(_ value: String) { print("String: \(value)") }
func print(_ value: Double) { print("Double: \(value)") }
print(42) // Int
print("Hi") // String
重载依据:参数数量、类型、标签
十三、泛型函数
func swapValues<T>(_ a: inout T, _ b: inout T) {
(a, b) = (b, a)
}
var x = 1, y = 2
swapValues(&x, &y)
print(x, y) // 2 1
十四、高阶函数实战
let numbers = [1, 6, 2, 8, 3, 9]
// map
let squared = numbers.map { $0 * $0 }
// filter
let evens = numbers.filter { $0 % 2 == 0 }
// reduce
let product = numbers.reduce(1, *)
// sorted
let sorted = numbers.sorted { $0 > $1 }
// 链式
let result = numbers
.filter { $0 > 5 }
.map { $0 * 10 }
.reduce(0, +)
十五、函数式编程最佳实践
| 场景 | 推荐 |
|---|---|
| 转换 | map |
| 过滤 | filter |
| 聚合 | reduce |
| 排序 | sorted(by:) |
| 异步回调 | @escaping |
| 延迟条件 | @autoclosure |
十六、实战项目:计算器引擎
enum Operator: String {
case add = "+", subtract = "-", multiply = "*", divide = "/"
func apply(_ a: Double, _ b: Double) -> Double {
switch self {
case .add: return a + b
case .subtract: return a - b
case .multiply: return a * b
case .divide: return a / b
}
}
}
class Calculator {
func calculate(_ a: Double, _ op: Operator, _ b: Double) -> Double {
return op.apply(a, b)
}
// 支持字符串表达式
func evaluate(_ expression: String) throws -> Double {
let parts = expression.components(separatedBy: .whitespaces)
guard parts.count == 3,
let a = Double(parts[0]),
let op = Operator(rawValue: parts[1]),
let b = Double(parts[2]) else {
throw NSError(domain: "CalcError", code: 1, userInfo: [NSLocalizedDescriptionKey: "无效表达式"])
}
return calculate(a, op, b)
}
}
// 使用
let calc = Calculator()
print(calc.calculate(10, .add, 5)) // 15
do {
let result = try calc.evaluate("10 + 5")
print(result) // 15
} catch {
print("错误:\(error)")
}
十七、函数速查表
| 特性 | 语法 |
|---|---|
| 无返回值 | -> Void 或省略 |
| 多返回值 | -> (Int, String) |
| 默认参数 | name: String = "Guest" |
| 可变参数 | numbers: Int... |
| inout | inout Int, 调用 &x |
| 函数类型 | (Int) -> String |
| @escaping | @escaping () -> Void |
| throws | throws -> Double |
| 泛型 | <T>(T) -> T |
十八、练习题(当场写!)
// 1. 实现一个支持链式调用的加法函数
func chainAdd(_ value: Int) -> (Int) -> Int {
// 返回一个闭包
}
// 2. 写一个 @autoclosure 版本的 assert
func myAssert(_ condition: @autoclosure () -> Bool, message: String) {
// 你的代码
}
// 3. 实现一个高阶函数:两次调用
func twice<T>(_ value: T, apply: (T) -> T) -> T {
// 你的代码
}
答案(展开查看)
点击查看答案
// 1.
func chainAdd(_ value: Int) -> (Int) -> Int {
return { $0 + value }
}
// 使用
let add5 = chainAdd(5)
print(add5(10)) // 15
print(chainAdd(3)(7)) // 10
// 2.
func myAssert(_ condition: @autoclosure () -> Bool, message: String) {
if !condition() {
print("断言失败:\(message)")
}
}
// 使用
myAssert(1 > 2, message: "数学崩溃了")
// 3.
func twice<T>(_ value: T, apply: (T) -> T) -> T {
return apply(apply(value))
}
// 使用
let result = twice(5) { $0 * 2 } // 5 → 10 → 20
总结:函数黄金法则
| 法则 | 说明 |
|---|---|
| 1. 优先用返回值而非 inout | 纯函数更安全 |
| 2. 异步回调加 @escaping | 防止内存泄漏 |
| 3. 复杂逻辑用高阶函数 | map/filter/reduce |
| 4. 默认参数放最后 | 保持调用清晰 |
| 5. 错误处理用 throws | 而不是 Optional |
| 6. 函数类型命名清晰 | (User) -> Bool |
你已完全掌握 Swift 函数!
回复关键词继续学习:
Swift 闭包深入Swift 函数式编程实战Swift 异步函数(async/await)Swift 属性包装器与函数
现在就写一个支持 add(1)(2)(3)() == 6 的链式加法函数!