Swift 函数

Swift 函数(Functions)全解析(2025 版)

“函数是一等公民” —— 掌握 参数、返回值、闭包、高阶函数、inout、@escaping,写出 优雅、灵活、高性能 的 Swift 代码!


一、函数核心概念

特性说明
一等公民可赋值、传参、返回
类型安全参数和返回值有明确类型
默认参数支持默认值
可变参数... 接收多个值
返回值支持 VoidOptional、元组
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...
inoutinout Int, 调用 &x
函数类型(Int) -> String
@escaping@escaping () -> Void
throwsthrows -> 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 的链式加法函数!

文章已创建 2481

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

相关文章

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部