闭包 #
一、闭包概述 #
闭包是自包含的功能代码块,可以在代码中被传递和使用。
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