iOS swift3 闭包的用法总结
一、什么是闭包:
- 闭包是自包含的函数代码块,可以在代码中被传递和使用。
- Swift 中的闭包与 C 和 Objective-C 中的代码块(blocks)以及其他一些编程语言中的匿名函数比较相似。
二、闭包的语法表达式:
{ (parameters/接收的参数) -> (return type/闭包返回值类型) in
statements/保存在闭包中需要执行的代码
}
三、闭包的使用例子:
- 闭包形式1
func testClosure1(){
// 1.typealias关键字的使用,跟oc中的typedef类似
typealias ClosureAdd = (_ num1:Int,_ num2:Int) -> Int // 给闭包起别名为:ClosureAdd
let closureAdd:ClosureAdd = {
(_ num1:Int,_ num2:Int) in
return num1+num2
}
let reslut = closureAdd(2, 3)
print("reslut = \(reslut)")
}
- 闭包形式2
func testClosure2(){
// 2.简化
let closureAdd:(_ num1:Int,_ num2:Int) -> Int
closureAdd = {
(_ num1:Int,_ num2:Int) in
return num1+num2
}
let reslut = closureAdd(2, 3)
print("reslut = \(reslut)")
}
- 闭包形式3
func testClosure3(){
// 3.简化(当闭包没有接收参数时,可省略in关键字)
let closureAdd:() -> Int
closureAdd = {
// () in // 可省略
return 100
}
let reslut = closureAdd()
print("reslut = \(reslut)")
}
- 闭包形式4
func testClosure4(){
// 4.简化(省略参数名,用$0,$1,$2,$3,...代替)
let closureAdd:(Int,Int) -> Int
closureAdd = {
return $0+$1
}
let reslut = closureAdd(2,3)
print("reslut = \(reslut)")
}
四、闭包的使用:值捕获
定义:
- Swift 中,可以捕获值的闭包的最简单形式是嵌套函数,也就是定义在其他函数的函数体内的函数。
- 嵌套函数可以捕获其外部函数所有的参数以及定义的常量和变量。
例子:
func testClosure5(){
// 值捕获
func makeIncrease(forIncrese num:Int) ->() -> Int{
var total = 0
// 嵌套函数,捕获上下文变量
func increastor() -> Int{
total += num
return total
}
return increastor // 返回函数类型为() -> Int
}
let increaseFunc1 = makeIncrease(forIncrese: 3)
print(increaseFunc1())// 3
print(increaseFunc1())// 6
print(increaseFunc1())// 9
let increaseFunc1_1 = increaseFunc1 // 引用同一个闭包
print(increaseFunc1_1())// 12
let increaseFunc2 = makeIncrease(forIncrese: 5) // 新建一个新的闭包
print(increaseFunc2())// 5
print(increaseFunc2())// 10
print(increaseFunc2())// 15
}
五、闭包的使用:尾随闭包
定义:
- 如果你需要将一个很长的闭包表达式作为最后一个参数传递给函数,可以使用尾随闭包来增强函数的可读性。
- 尾随闭包是一个书写在函数括号之后的闭包表达式,函数支持将其作为最后一个参数调用。
- 在使用尾随闭包时,你不用写出它的参数标签:
例子:
func testClosure6(){
// 参数:一个Int型参数,一个函数型参数,返回值:String型
func outputNameAndNumber(_ num:Int,nameFunc:(String) -> String) -> String{
let infoString:String
infoString = nameFunc("Peater")+"My num is \(num)"
return infoString
}
// 将闭包作为参数
//写法一: 不使用尾随闭包写法:
let result1 = outputNameAndNumber(1, nameFunc: {
(name:String)->String in
let infoName = "My name is \(name) "
return infoName})
print(result1)
//写法二: 使用尾随闭包写法:
let result2 = outputNameAndNumber(2){
(name:String)->String in
let infoName = "My name is \(name) "
return infoName
}
print(result2)
//写法三:可简化忽略返回值参数列表
let result3 = outputNameAndNumber(3){
(name:String) in
let infoName = "My name is \(name) "
return infoName
}
print(result3)
}
六、闭包的使用:逃逸闭包
定义:
- 当一个闭包作为参数传到一个函数中,但是这个闭包在函数返回之后才被执行,我们称该闭包从函数中逃逸。
- 当你定义接受闭包作为参数的函数时,你可以在参数名之前标注 @escaping,用来指明这个闭包是允许“逃逸”出这个函数的。
例子:
func testCloser7(){
// 关键字:@escaping
var closerArray:[(Int)->String] = [] // 定义一个变量数组:闭包类型
func escapingCloser(handle:@escaping (Int)->String){
closerArray.append(handle) // 将该闭包存入数组中
}
// 调用函数
escapingCloser(handle: {
(num:Int)->String in
return "My number is \(num)"
})
let num = 8
print(closerArray[0](num))
print(closerArray.first?(num))
}
七、闭包的使用:自动闭包
定义:
- 自动闭包是一种自动创建的闭包,用于包装传递给函数作为参数的表达式。
- 这种闭包不接受任何参数,当它被调用的时候,会返回被包装在其中的表达式的值。
- 这种便利语法让你能够省略闭包的花括号,用一个普通的表达式来代替显式的闭包。
例子:
func testCloser8(){
// 关键字:@autoclosure
// 作用:自动闭包让你能够延迟求值,因为直到你调用这个闭包,代码段才会被执行
// 例子一:
var nameArray:[String] = ["Tom","Mary","Lily"] // 定义一个变量数组:闭包类型
print(nameArray.count) // 3
let customer = {nameArray.remove(at: 0)}
print(nameArray.count) // 3
let name = customer()
print(name) // Tom
print(nameArray.count) // 2
// 例子二:将闭包作为参数传递给函数时,能获得同样的延时求值行为。
var doingWhat = "arrfu"
func namePrint(nameHandle:()->String){
print("调用前:",doingWhat) // 调用前: arrfu
print("调用闭包参数 nameHandle() 的结果为:\(nameHandle())") // arrfu is eating
print("调用后:",doingWhat) // arrfu is eating
}
// 传入闭包作为参数
namePrint(nameHandle: {doingWhat = doingWhat + " is eating"
return doingWhat })
// 例子二:利用自动闭包 @autoclosure 来获得延时求值行为
var doingWhat1 = "arrfu"
func namePrint1(nameHandle:@autoclosure ()->String){
print("1.调用前:",doingWhat1) // 1.调用前: arrfu
print("1.调用闭包参数 nameHandle() 的结果为:\(nameHandle())")
print("1.调用后:",doingWhat1) // 1.调用后: arrfu is eating
}
func haveSomeFun() -> String{
doingWhat1 = doingWhat1 + " is eating"
return doingWhat1;
}
namePrint1(nameHandle: haveSomeFun()) // 可直接传入函数,而不是闭包
// 被 @autoclosure 标记的参数 nameHandle 将自动转化为一个闭包。
}
八、Demo 地址: https://github.com/arrfu/My-Swift3-Study/tree/master/swift3StudyDemo/JFClosuresDemo