闭包 #

一、闭包概述 #

闭包是自包含的功能代码块,可以在代码中被传递和使用。

1.1 闭包特点 #

  • 自包含的代码块
  • 可以捕获和存储上下文中的变量
  • 引用类型
  • 类似于其他语言的lambda或匿名函数

1.2 闭包表达式语法 #

swift
{ (parameters) -> ReturnType in
    statements
}

二、闭包表达式 #

2.1 完整语法 #

swift
let add: (Int, Int) -> Int = { (a: Int, b: Int) -> Int in
    return a + b
}

print(add(1, 2))

2.2 类型推断 #

swift
let add: (Int, Int) -> Int = { a, b in
    return a + b
}

print(add(1, 2))

2.3 隐式返回 #

swift
let add: (Int, Int) -> Int = { a, b in a + b }

print(add(1, 2))

2.4 简写参数名 #

swift
let add: (Int, Int) -> Int = { $0 + $1 }

print(add(1, 2))

2.5 尾随闭包 #

swift
let numbers = [1, 2, 3, 4, 5]

let doubled = numbers.map { $0 * 2 }
print(doubled)

let evenNumbers = numbers.filter { $0 % 2 == 0 }
print(evenNumbers)

let sum = numbers.reduce(0) { $0 + $1 }
print(sum)

三、闭包作为参数 #

3.1 基本用法 #

swift
func execute(_ closure: () -> Void) {
    closure()
}

execute {
    print("闭包执行了")
}

3.2 带参数的闭包 #

swift
func process(_ value: Int, transform: (Int) -> Int) -> Int {
    return transform(value)
}

let result = process(5) { $0 * 2 }
print(result)

3.3 多闭包参数 #

swift
func fetchData(
    onSuccess: @escaping (Data) -> Void,
    onFailure: @escaping (Error) -> Void
) {
    let success = true
    
    if success {
        onSuccess(Data())
    } else {
        onFailure(NSError(domain: "Error", code: -1))
    }
}

fetchData(
    onSuccess: { data in
        print("成功: \(data)")
    },
    onFailure: { error in
        print("失败: \(error)")
    }
)

四、捕获值 #

4.1 捕获变量 #

swift
func makeIncrementer() -> () -> Int {
    var count = 0
    
    return {
        count += 1
        return count
    }
}

let incrementer = makeIncrementer()
print(incrementer())
print(incrementer())
print(incrementer())

4.2 值捕获 vs 引用捕获 #

swift
func makeIncrementers() -> [() -> Int] {
    var incrementers: [() -> Int] = []
    
    for i in 1...3 {
        incrementers.append {
            return i
        }
    }
    
    return incrementers
}

let incrementers = makeIncrementers()
incrementers.forEach { print($0()) }

4.3 捕获列表 #

swift
func makeIncrementers() -> [() -> Int] {
    var incrementers: [() -> Int] = []
    var i = 0
    
    for _ in 1...3 {
        i += 1
        incrementers.append { [i] in
            return i
        }
    }
    
    return incrementers
}

let incrementers = makeIncrementers()
incrementers.forEach { print($0()) }

4.4 捕获self #

swift
class Counter {
    var count = 0
    
    lazy var increment: () -> Int = { [weak self] in
        self?.count += 1
        return self?.count ?? 0
    }
}

let counter = Counter()
print(counter.increment())
print(counter.increment())

五、逃逸闭包 #

5.1 @escaping #

swift
var completions: [() -> Void] = []

func storeCompletion(_ completion: @escaping () -> Void) {
    completions.append(completion)
}

storeCompletion {
    print("执行闭包")
}

completions.forEach { $0() }

5.2 异步回调 #

swift
func fetchData(completion: @escaping (Result<Data, Error>) -> Void) {
    DispatchQueue.global().async {
        Thread.sleep(forTimeInterval: 1)
        
        DispatchQueue.main.async {
            completion(.success(Data()))
        }
    }
}

fetchData { result in
    switch result {
    case .success(let data):
        print("成功: \(data)")
    case .failure(let error):
        print("失败: \(error)")
    }
}

5.3 逃逸闭包中的self #

swift
class NetworkManager {
    var data: Data?
    
    func fetchData() {
        fetchDataFromNetwork { [weak self] result in
            switch result {
            case .success(let data):
                self?.data = data
            case .failure:
                break
            }
        }
    }
    
    func fetchDataFromNetwork(completion: @escaping (Result<Data, Error>) -> Void) {
        DispatchQueue.global().asyncAfter(deadline: .now() + 1) {
            completion(.success(Data()))
        }
    }
}

六、自动闭包 #

6.1 @autoclosure #

swift
func assert(_ condition: @autoclosure () -> Bool, _ message: String) {
    if !condition() {
        print("Assertion failed: \(message)")
    }
}

assert(1 + 1 == 2, "Math is broken")

6.2 延迟求值 #

swift
func logIfDebug(_ message: @autoclosure () -> String) {
    #if DEBUG
    print(message())
    #endif
}

logIfDebug("This is a debug message")

6.3 实际应用 #

swift
func or(_ first: Bool, _ second: @autoclosure () -> Bool) -> Bool {
    return first ? true : second()
}

let result = or(true, { print("不会执行"); return false }())
print(result)

七、实际应用 #

7.1 数组排序 #

swift
let numbers = [3, 1, 4, 1, 5, 9, 2, 6]

let ascending = numbers.sorted { $0 < $1 }
print(ascending)

let descending = numbers.sorted { $0 > $1 }
print(descending)

7.2 异步操作 #

swift
func performAsync(_ work: @escaping () -> Void, completion: @escaping () -> Void) {
    DispatchQueue.global().async {
        work()
        DispatchQueue.main.async {
            completion()
        }
    }
}

performAsync({
    print("执行工作")
}) {
    print("工作完成")
}

7.3 动画 #

swift
UIView.animate(withDuration: 0.3) {
    view.alpha = 0
} completion: { _ in
    view.removeFromSuperview()
}

7.4 网络请求 #

swift
func request<T: Decodable>(
    url: URL,
    completion: @escaping (Result<T, Error>) -> Void
) {
    URLSession.shared.dataTask(with: url) { data, response, error in
        guard let data = data, error == nil else {
            completion(.failure(error!))
            return
        }
        
        do {
            let decoded = try JSONDecoder().decode(T.self, from: data)
            completion(.success(decoded))
        } catch {
            completion(.failure(error))
        }
    }.resume()
}

八、闭包与内存管理 #

8.1 循环引用 #

swift
class ViewController {
    var closure: (() -> Void)?
    
    func setupClosure() {
        closure = {
            print(self)
        }
    }
}

8.2 使用weak打破循环引用 #

swift
class ViewController {
    var closure: (() -> Void)?
    
    func setupClosure() {
        closure = { [weak self] in
            guard let self = self else { return }
            print(self)
        }
    }
}

8.3 使用unowned #

swift
class ViewController {
    var closure: (() -> Void)?
    
    func setupClosure() {
        closure = { [unowned self] in
            print(self)
        }
    }
}

九、总结 #

本章学习了Swift闭包:

  • 闭包表达式:完整语法、简写形式
  • 捕获值:捕获上下文变量
  • 逃逸闭包:@escaping标记
  • 自动闭包:@autoclosure延迟求值

最佳实践:

  • 使用尾随闭包提高可读性
  • 注意循环引用问题
  • 合理使用捕获列表
  • 逃逸闭包使用weak self

下一章,我们将学习高阶函数!

最后更新:2026-03-26