前语
Swift 是一门现代化的编程言语,它在许多方面都充满创新和便利性。在 Swift 中,闭包 是一项强壮的特性,它为开发者供给了一种灵敏、轻量级的函数式编程办法。本文我将总结一下我深化研究后关于 Swift中 闭包 的概念,品种和写法以及一些实践的运用。
一、闭包的概念
信任大家网上一搜都查到这么一句话:
闭包是一种自包含的功用代码块,是能够被传递和用作参数的函数。
那么这句话应该怎么了解呢?需求了解这句话,需求首先了解 Swift 中函数是一等公民(First-Class Citizen)的概念。
所谓”榜首等公民”(first class),指的是其他数据类型相同,处于相等位置,能够赋值给其他变量,也能够作为参数,传入另一个函数,或许作为其他函数的回来值。
而Swift 中的函数和闭包都是一等公民,因而闭包既能够被当作参数传递给函数,也能够赋值给变量,还能够作为函数的回来值。
二、闭包的品种
闭包有三种办法:大局函数、嵌套函数和闭包表达式。
1.大局函数
大局函数是一个特别的闭包。他具有姓名但不捕获任何值,界说在大局效果域内,例如以下代码:
// 大局效果域中的函数
//`person是`greet` 函数的参数,而不是捕获的值。
func greet(person: String) -> String {
return "Hello, (person)!"
}
let greeting = greet(person: "Alice")
print(greeting) // 输出: Hello, Alice!
2.嵌套函数
嵌套函数是在其他函数内部界说的函数,也是一个特别的闭包,它具有姓名,能够捕获其包含函数的参数和常量。嵌套函数在外部是不行见的,除非被包含的函数调用了它。
func outerFunction() -> (String) -> String {
func innerFunction(name: String) -> String {
return "Welcome, (name)!"
}
return innerFunction
}
let welcome = outerFunction()
let message = welcome("Bob")
print(message) // 输出: Welcome, Bob!
嵌套函数捕获的值会被保留在内存中,直到闭包不再被引用。然后确保了鄙人一次履行函数时,之前捕获的值仍旧存在,也无需咱们忧虑内存管理问题
func outerFunction() -> () -> Void {
var value = 10
func innerFunction() {
value += 5
print(value)
}
return innerFunction
}
let closure = outerFunction()
closure() // 输出 15
closure() // 输出 20
3.闭包表达式
3.1 闭包表达式的界说和格局
闭包表达式是一种更为简练的办法界说闭包,通常在需求时进行直接界说和运用,也能够捕获上下文的变量/常量。
闭包表达式的基本语法包含参数列表、回来箭头和代码块。格局如下:
{ (parameters) -> returnType in
//statements
}
举2个例子,分别是 无参数无回来值 和 有参数有回来值(自己能够推导出别的两种写法: 无参数有回来值 和 有参数无回来值)
//无参数无回来值-写法1
let log1: ()->Void = { ()->Void in
print("closure")
}
//无参数无回来值-写法2
let log2 = { ()->Void in
print("closure")
}
//调用办法
log1()
log2()
//有参数有回来值-写法1
let log1: (_ str:String)->Void = { (str:String)->Void in
print(str)
return str
}
//有参数有回来值-写法2
let log2: (_ str:String)->Void = { (str:String)->Void in
print(str)
return str
}
//调用办法
let str1 = log1("closure")
let str1 = log2("closure")
3.2 闭包表达式的优化
在 Swift 中,闭包表达式具有简练、灵敏的语法,并支撑一些优化办法。以下是闭包表达式的优化办法:
- 简化参数和回来类型
能够省掉闭包参数和回来类型的声明,让 Swift 根据上下文进行类型揣度。
// 完好办法
let sum = { (a: Int, b: Int) -> Int in
return a + b
}
// 优化办法(优化了参数类型声明)
let sumOptimized = { a,b -> Int in
return a + b
}
用体系供给的排序函数sorted
更直观,由于该函数是比照两个Int参数,回来谁更大谁更小的布尔值判别,即
{ (num1: Int, num2: Int) -> Bool in
return num1 < num2
}
所以能够省掉闭包参数和回来类型的声明,如下:
// 完好办法
let sortNumbers = numbers.sorted { (num1:Int, num2:Int) -> Bool in
return num1 < num2
}
// 优化办法(优化了参数类型和回来类型声明)
let sumSortNumbers = numbers.sorted { num1,num2 in
return num1 < num2
}
- 单表达式闭包
如果闭包只要一条句子,能够省掉 return
关键字。
// 完好办法
let square = { (number: Int) -> Int in
return number * number
}
// 优化办法
let squareOptimized = { (number: Int) -> Int in number * number }
- 参数名缩写
如果闭包体的参数和回来值能够被主动揣度,那么能够运用 $0
, $1
, $2
, … 来代替闭包中的参数名,然后省掉 in
关键字。(如果闭包体只要一行,而且该行内容能够被主动揣度,不仅能省掉 return
关键字,甚至还能够省掉 in
关键字)
let numbers = [1, 2, 3, 4, 5]
// 完好办法
let mappedNumbers = numbers.map({ (number: Int) -> Int in
return number * 2
})
// 优化办法(闭包体只要一行,能够省掉 `return` 关键字)
let mappedNumbersOptimized = numbers.map { $0 * 2 }
- 跟随闭包
在 Swift 中,如果函数的最后一个参数是闭包,而你又需求运用闭包作为函数的参数,那么就能够运用跟随闭包。
跟随闭包是一种在函数调用时编写的闭包表达式,它被写在函数调用的括号之后,跟随闭包的语法允许省掉闭包的参数标签,让函数愈加清晰易读。
func performOperation(_ name:String, _ operation: () -> Void) {
// 履行操作
operation()
}
// 完好办法
performOperation("perform",{
print("Performing operation")
})
// 优化办法
performOperation("perform") {
print("Performing operation")
}
若函数只需求闭包表达式一个参数,当运用跟随闭包时,能够把()
也省掉掉。
func performOperation(_ operation: () -> Void) {
// 履行操作
operation()
}
// 完好办法
performOperation({
print("Performing operation")
})
// 优化办法
performOperation{
print("Performing operation")
}
三、逃逸闭包
逃逸闭包(Escaping Closures)是指在闭包被传递到函数之外的效果域,或许在函数履行完之后才被调用的闭包。(在 Swift 中,闭包默许是非逃逸的,即在函数结束前履行。)
需求运用 @escaping
标记逃逸闭包,以便在函数履行结束后继续存在。
逃逸闭包通常用于异步操作,例如在后台履行任务后履行闭包。
var completionHandlers: [() -> Void] = []
func doSomething(completion: @escaping () -> Void) {
completionHandlers.append(completion)
}
func executeCompletionHandlers() {
for handler in completionHandlers {
handler()
}
}
// 逃逸闭包
doSomething {
print("Task completed!")
}
// 履行逃逸闭包
executeCompletionHandlers() // 输出: Task completed!
在这个例子中,doSomething
函数接受一个逃逸闭包作为参数,并将其增加到 completionHandlers
数组中。稍后,通过调用 executeCompletionHandlers
函数,之前增加的闭包会被履行。
四、闭包的运用场景
闭包在 Swift 中有许多运用场景,其间一些包含:
1. 排序操作: 运用闭包对数组进行自界说排序。
let numbers = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5]
let sortedNumbers = numbers.sorted { $0 < $1 }
print(sortedNumbers) // 输出: [1, 1, 2, 3, 3, 4, 5, 5, 5, 6, 9]
2. 函数式编程: 使用闭包进行函数式编程,完成高阶函数的功用。
let numbers = [1, 2, 3, 4, 5]
let doubledNumbers = numbers.map { $0 * 2 }
print(doubledNumbers) // 输出: [2, 4, 6, 8, 10]
3. UI 动画: 运用闭包完成 UIView 动画的 completion 部分。
UIView.animate(withDuration: 1.0, animations: {
// 动画效果
}, completion: { _ in
// 动画完成后履行的闭包
print("Animation completed!")
})
总结
Swift 中的闭包是一项强壮而灵敏的特性,它为开发者供给了一种简练、高雅的函数式编程办法。深化了解和娴熟运用闭包,将有助于提高 Swift 编程的功率和代码质量。