• swift 【block】


    在 swift中可以用 func 定义一个函数,也可以用闭包表达式定义一个函数

    1. func sum(v1:Int, v2:Int) -> Int { v1 + v2 }
    2. let sum2 = { (v1:Int, v2:Int) -> Int in
    3. return v1 + v2
    4. }
    5. sum(v1: 10, v2: 20)//func定义的函数
    6. sum2(10, 20)//闭包表达式定义的函数
    1. func sun(param1:Int, param2:Int, test:( Int, Int) -> Int) {
    2. print(test(param1, param2))
    3. }
    4. sun(param1:20 , param2:20, test:{
    5. (v1:Int, v2:Int) -> Int in
    6. return v1 + v2
    7. })
    8. //闭包表达式简写
    9. sun(param1:20 , param2:20, test:{
    10. v1, v2 -> Int in
    11. return v1 + v2
    12. })
    13. sun(param1:20 , param2:20, test:{
    14. v1, v2 in
    15. return v1 + v2
    16. })
    17. //闭包表达式隐式返回
    18. sun(param1:20 , param2:20, test:{
    19. v1, v2 in v1 + v2
    20. })
    21. //参数名称简写
    22. sun(param1:20 , param2:20, test:{
    23. $0 + $1
    24. })
    25. //函数式闭包
    26. sun(param1: 2, param2: 3, test: +)

    • 尾随闭包

    最后一个参数是闭包表达式的时候,可以独立于前面的参数,写在函数参数外面的闭包表达式,使结构看起来再加清晰整洁,属于结构优化,默认闭包表达式作为参数的时候采用尾随闭包的形式。

    1. sun(param1: 12, param2: 13) { (v1:Int, v2:Int) -> Int in
    2. return v1 + v2
    3. }
    4. //尾随闭包表达式
    5. sun(param1: 12, param2: 13) { v1, v2 in
    6. v1 + v2
    7. }
    8. //尾随闭包表达式简写
    9. sun(param1: 20, param2: 12) { return $0 + $1 }
    10. //尾随闭包表达式简写
    11. sun(param1: 10, param2: 12) { $0 + $1 }
    12. sun(param1: 10, param2: 12) { $0 + $1 }
    13. sun(param1: 2, param2: 3, test: +)

    • 自动闭包

    顾名思义根据传入的参数,自动生成闭包;延迟执行,属于性能优化,除些之外也属于结构优化,调用者无需关心参数类型,用@autoclosure 修饰。

    @autoclosure 只支持()->T 的格式参数,并且不仅仅只支持最后一个参数。

    系统的合并运算符??属于自动闭包。

    自动闭包允许你延迟处理,因此闭包内部的代码直到你调用它的时候才会运行。

    1. //添加 @autoclosure 关键字, 当闭包被调用的时候,会返回被包装在其中的表达式的值
    2. public func assert(_ condition: @autoclosure () -> Bool, _ message: @autoclosure () -> String = String(), file: StaticString = #file, line: UInt = #line) {
    3. if !condition() {
    4. print(message())
    5. }
    6. }
    7. let number = 3
    8. assert(number > 3, "number 不大于3") //输出: number 不大于3
    1. //自动闭包允许延迟处理
    2. var person = ["zhangsan", "lisi", "wangwu", "zhailiu"]
    3. print(person.count) // 输出: 4
    4. let deletePerson = { person.remove(at: 0) }
    5. print(person.count) //此时输出还是 4,因为没有调用闭包没有被调用,闭包里的代码没有被执行
    6. //此时调用闭包
    7. print(deletePerson()) //输出 "zhangsan"
    8. print(person.count) //输出: 3
    1. //闭包作为实际参数传递给函数时,能获得同样的延时求值行为
    2. //闭包作为实参, 可以显示的使用闭包
    3. var person = ["zhangsan", "lisi", "wangwu", "zhailiu"]
    4. func serve(customer customerProvider: () -> String) {
    5. print("Now serving \(customerProvider())!")
    6. }
    7. //函数接受一个返回顾客名字的显式的闭包
    8. serve(customer: { person.remove(at: 0) }) //打印: Now serving zhangsan!
    1. //自动闭包作为实际参数
    2. var person = ["zhangsan", "lisi", "wangwu", "zhailiu"]
    3. //customerProvider 参数将自动转化为一个闭包,因为该参数被标记了 @autoclosure 特性
    4. func serve(customer customerProvider: @autoclosure () -> String) {
    5. print("Now serving \(customerProvider())!")
    6. }
    7. serve(customer: person.remove(at: 0)) //打印: Now serving zhangsan!

    • 自动+逃逸

    1. //自动闭包允许逃逸,同时使用 @autoclosure 和 @escaping 标志
    2. var customerInLine = ["zhangsan", "lisi", "wangwu", "zhaoliu"]
    3. var customerProviders: [() -> String] = []
    4. func collectionCustomerProviders(_ customerProvider: @autoclosure @escaping () -> String) {
    5. customerProviders.append(customerProvider)
    6. }
    7. print(customerProviders.count) //打印: 0
    8. collectionCustomerProviders(customerInLine.remove(at: 0))
    9. collectionCustomerProviders(customerInLine.remove(at: 0))
    10. print(customerInLine.count) //打印: 4
    11. print(customerProviders.count) //打印: 2
    12. for c in customerProviders {
    13. print("Now serving \(c())")
    14. }
    15. /*
    16. Now serving zhangsan
    17. Now serving lisi
    18. */

    collectCustomerProviders(_ : ) 函数并没有调用传入的 customerProvider 闭包,而是将闭包追加到了 customerProviders 数组中。
    这个数组定义在函数作用域范围外,这意味着数组内的闭包能够在函数返回之后被调用。
    因此,customerProvider 参数必须允许“逃逸”出函数作用域。

    • swift 闭包值捕获

    • 闭包可以对外部函数的变量、常量进行捕获;
    • 闭包捕获时机是在函数执行完,return 时再去捕获
    • 当函数里有多个闭包时,只会对变量、常量捕获一次,多个闭包对捕获的变量、常量共享
    • 闭包不会对全局变量进行捕获

    闭包可以在其被定义的上下文中捕获常量或者变量。即是定义这些常量和变量的原作用域已经不存在了,闭包仍然可以在闭包函数体内引用和修改这些值。

    • 闭包类型

    和类一样,闭包也是引用类型

    • 闭包

    闭包和闭包表达式并不一是一个东西,半包表达式是函数的另外一种定义,而闭包是一个函数和它所捕获变量/常量环境的组合;

    一般指定义在函数内部的函数;一般它捕获的是外层函数的局部变量/常量;

    闭包和和闭包表达式的区别?

    闭包表达式是:函数的另外一种表现形式,为了实现简介和高效,有不同的表现形式,例如自动闭包,尾随闭包;
    闭包是:封装在函数中的函数或者闭包表达式,且捕获了局部变量的运行环境。它运用了闭包表达式,但闭包表达式不是闭包。

    •  循环引用的问题

      objective-c解决闭包的循环引用问题一般是先声明__weak typedef(weakSelf) = self;然后使用weakSelf对本类的属性调用。
      swift中也有类似于objective-c中的方法:首先是声明:weak var weakSelf = self;然后使用weakSelf对本类的属性调用。self可能会为nil,所以需要用var。

    • 闭包内修改外部变量

    在objective-c中,我们通常使用__block来声明一个变量,这样就可以在闭包内对这个变量进行修改。
    在swift中没有__block这种关键字,但是swift中的闭包是做了优化处理,是可以直接捕获上下文中的变量。所以可以直接在闭包中对变量进行修改。

  • 相关阅读:
    数据结构编写程序出现syntax error before '&' token怎么修改
    关系数据理论
    Logstash实现MySql数据近实时同步ElasticSearch搜索服务
    就业核心指导
    【微信小程序】【AR】threejs-miniprogram 安装(76/100)
    k8s基础 随笔
    MySQL进阶(B)
    二叉树的遍历(c++)
    Python利用字典计数
    用Spring Boot 3.2虚拟线程搭建静态文件服务器有多快?
  • 原文地址:https://blog.csdn.net/xiaobo0134/article/details/125888211