Swift——闭包(Closure)

一、闭包表达式

{

    (参数列表) -> 返回值类型 in

    函数体代码

}

1、在Swift中,可有通过func 定义一个函数,也可以通过闭包表达式定义一个函数

func sum(_ a:Int, _ b:Int) ->Int {a + b}
var fn = {
    (a: Int, b :Int) -> Int in
    a + b
}
//调用
fn(10,20)

2、闭包表达式的简写

func sum(a: Int , b: Int, fn: (Int, Int) -> Int){
    print(fn(a,b))
}

//方式一
sum(a: 30, b: 40, fn: {
    (a:Int, b:Int) ->Int in
    a + b
})

//方式二
sum(a: 40, b: 30, fn: {
    a,b in
    a + b
})

//方式三
sum(a: 30, b: 40, fn: {$0 + $1})
//方式四
sum(a: 50, b: 40, fn: + )

 

二、尾随闭包

如果将一个很长的闭包表达式作为函数的最后一个实参,使用尾随闭包也可以增强函数的可读性;尾随闭包是一个被书写在函数调用括号外面的闭包表达式;如果闭包表达式是函数的唯一实参,而且使用了尾随闭包的语法,那就不需要在函数名后边写圆括号。

func sum(a: Int , b: Int, fn: (Int, Int) -> Int){
    print(fn(a,b))
}

sum(a: 40, b: 40) { (a,b) -> Int in
    return a + b
}
sum(a: 40, b: 30) { $0 + $1 }

// 唯一实参
func exec(fn:(Int,Int) -> Int) {
    print(fn(1,4))
}
exec { (a, b) -> Int in
    a + b
}
exec(){$0 + $1}
exec{$0 + $1}

三、闭包

 一个函数和它所捕获的变量/常量环境组合起来,称为闭包

 一般指定义在函数内部的函数

 一般它捕获的是外层函数的局部变量/常量;创建一块堆空间

typealias Fn = (Int) -> Int

func getFn() -> Fn {
    var num = 0
    func plus(_ i: Int) -> Int {
        num += i
        return num
    }
    return plus(_:) //返回的plus 和num形成了闭包 ;num 捕获生成堆空间
}
var fn = getFn()
print(fn(1)) //1
print(fn(2)) //3
print(fn(3)) //6

 

四、自动闭包

自动闭包是一种自动创建的闭包,用于包装传递给函数作为参数的表达式。这种闭包不接受任何参数,当它被调用的时候,会返回被包装在其中的表达式的值。这种便利语法让你能够省略闭包的花括号,用一个普通的表达式来代替显式的闭包。

自动闭包让你能够延迟求值,因为直到你调用这个闭包,代码段才会被执行。延迟求值对于那些有副作用(Side Effect)和高计算成本的代码来说是很有益处的,因为它使得你能控制代码的执行时机。下面的代码展示了闭包如何延时求值。

func getFirstPositive(_ v1: Int ,_ v2: Int) -> Int {
    return v1 > 0 ? v1 : v2
}

print(getFirstPositive(10, 20)) // 10
print(getFirstPositive(-2, 20)) // 20
print(getFirstPositive(0, -4)) // -4

函数类型的参数
改成函数类型的参数, 可以v2延迟加载
func getFirstPositive(_ v1:Int,_ v2:()-> Int) ->Int {
    return v1 > 0 ? v1 : v2()
}

var a = getFirstPositive(10, {30})
//尾随闭包
var b = getFirstPositive(-20){40}
print(a)
print(b)

//自动闭包
func getFirstPositive(_ v1:Int, _ v2: @autoclosure ()-> Int ) -> Int {
    return v1 > 0 ? v1 : v2()
}
print(getFirstPositive(-20, 40))

 @autoclosure 会自动将 40 封装成闭包{40}

 @autoclosure 只支持 ()-> T 格式的参数

 @autoclosure 并非只支持最后一个参数

 空合并运算符 ?? 使用了 @autoclosure 技术

 有 @autoclosure 、无 @autoclosure,构成了函数重载

五、逃逸闭包

 非逃逸闭包、逃逸闭包,一般都是当做参数传递给函数

 非逃逸闭包:闭包调用发生在函数结束前,闭包调用在函数作用域内

 逃逸闭包: 闭包有可能在函数结束后调用,闭包调用逃离了函数的作用域,需要通过@escaping声明

typealias Fn = () -> ()

//fn 是非逃逸闭包
func test1(_ fn:Fn){
    fn()
}

//逃逸闭包
func test2(_ fn:@escaping Fn){
    print("开始")
    DispatchQueue.global().async {
        print("进入")
        fn()
    }
    print("结束")
}

test2 {
    print("调用")
}
//开始 结束 进入 调用

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值