Swift 闭包(block)详解

1、闭包

Swift对闭包进行了简化:

  • 利用上下文推断参数和返回值类型
  • 隐式返回单表达式闭包,即单表达式闭包可以省略return关键字
  • 参数名称缩写
  • 尾随(Trailing)闭包语法

先来看一个排序的例子,数组的降序排列

let usernames = ["Wangwu", "Lisi", "Xiaoming", "Zhangsan"]
func backWards(s1: String, s2: String) -> Bool
{
    return s1 > s2
}
let resultName1 = usernames.sorted(by: backWards)
//resultName1: ["Zhangsan", "Xiaoming", "Wangwu", "Lisi"]

 1.1 闭包表达式语法

{ (parameters) -> returnType in
      statements
}

1.2 单表达式闭包隐式返回

单行表达式闭包可以通过省略return关键字来隐式返回单行表达式的结果

let resultName2 = usernames.sorted { s1, s2 in s1 > s2 }

1.3 参数名称缩写

let resultName3 = usernames.sorted { $0 > $1 }

1.4 函数式闭包 

let resultName4 = usernames.sorted(by: >)

2. 捕获值(Capturing Values)

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

3.闭包是引用类型(Closures Are Reference Types)

和类一样,必要也是引用类型

4. 尾随闭包(Trailing Closures))

尾随闭包是一个书写在函数括号之后的闭包表达式,函数支持将其作为最后一个参数调用:

        let numReult2 = caculateTwoNumbers(num1: 3, num2: 4) {  $0 * $1 }
        print(numReult2)
    
    func caculateTwoNumbers(num1: Int, num2: Int, CaluFunction: (Int, Int) -> Int) -> Int{
        return CaluFunction(num1, num2)
    }

5. 逃逸闭包(@escaping)

    func mainFunc(){
        //调用函数
        doSomething(paramClosure: {print("hello")})
        doSomething(paramClosure:{print("word!")})
        //逃逸调用闭包
        for closurePrama in functionArray {
            closurePrama()
        }
        //非逃逸闭包
        someFunctionWithNonescapingClosure { (a) in
            print(a)
        }
    }
    //声明一个存放函数的数组
    var functionArray: [() -> Void] = []
    //定义一个接收闭包参数的函数,如果定义非逃逸函数 func doSomething(@noescape paramClosure:() -> Void) 就会编译错误
    func doSomething(paramClosure:@escaping  () -> Void){
        //把参数放入数组中,用于逃逸调用
        functionArray.append(paramClosure)
    }
    //非逃逸闭包 默认@noescape 可以省略不写
    func someFunctionWithNonescapingClosure(closure: (_ num:Int) -> Void) {
        let a = 1
        closure(a)
    }

6、noescape是非逃逸的意思。

@noescape关键字代码中扮演了一个标注的作用:来说明一个闭包参数,该闭包参数与此API是同步的,它只在此API中被调用。只要该API运行结束,该闭包的生命周期就结束。也就是说,该闭包逃不出该API的手掌心。哈哈哈哈!它对编译器和API调用者来说:编译器会对代码做一些优化,而API调用者则可以放心大胆的使用该API,不用因为担心造成引用循环而去使用捕获列表。同时在其中调用实例变量或实例方法的时候可以不使用"self."

      但是!如何使用这个@noescape标注,这是需要正确的姿势的!

      上面的论述,只有在闭包是临时创建,即没有被API外部的任何其他属性或全局变量持有的前提下才成立!!

func withLock(@noescape perform closure: () -> Void) {
    myLock.lock()
    closure()
    myLock.unlock()
}

In  Objective-C

- (void)performWithLock:(__attribute__((noescape)) void (^)())block {  // exposed as @noescape to Swift
    [myLock lock];
    block();
    [myLock unlock];
}

面试题:调用Masonry的block为何不用weak?

原因就是使用了栈block,都是用NS_NOESCAPE修饰block.编译器会相应地做一些优化,例如去掉一些多余的对self的捕获、retain、release操作。

- (NSArray *)mas_makeConstraints:(void(NS_NOESCAPE ^)(MASConstraintMaker *make))block;
- (NSArray *)mas_updateConstraints:(void(NS_NOESCAPE ^)(MASConstraintMaker *make))block;
- (NSArray *)mas_remakeConstraints:(void(NS_NOESCAPE ^)(MASConstraintMaker *make))block;

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Swift 中的闭包是一个自包含的函数代码块,可以在代码中被传递和使用。闭包可以捕获和存储其所在上下文中任意常量和变量的引用。Swift 中的闭包类似于 C 和 Objective-C 中的 blocks、以及其他一些编程语言中的 lambdas。 闭包有以下三种形式: 1. 全局函数,有名字但不能捕获任何值。 2. 嵌套函数,有名字,也能捕获其封闭函数内的值。 3. 闭包表达式,没有名字,使用轻量级语法,可以捕获上下文中的值。 闭包表达式的基本语法如下: ``` { (parameters) -> return type in statements } ``` 其中 `parameters` 为参数列表,可以为空;`return type` 为返回类型,也可以为空;`statements` 为闭包体,包含了要执行的代码。 例如,下面的代码定义了一个接受两个整数参数并返回它们之和的闭包: ``` let sum = { (a: Int, b: Int) -> Int in return a + b } ``` 可以像函数一样调用这个闭包: ``` let result = sum(1, 2) print(result) // 输出 3 ``` 闭包可以作为函数的参数或返回值。例如,下面的代码定义了一个接受一个整型数组和一个闭包参数的函数 `apply`: ``` func apply(_ array: [Int], _ transform: (Int) -> Int) -> [Int] { var result = [Int]() for element in array { result.append(transform(element)) } return result } ``` 可以使用闭包表达式作为 `transform` 参数传递: ``` let numbers = [1, 2, 3, 4, 5] let squared = apply(numbers, { (number) -> Int in return number * number }) print(squared) // 输出 [1, 4, 9, 16, 25] ``` 闭包还支持尾随闭包语法,可以将闭包表达式作为函数的最后一个参数传递,并将其放在圆括号之外。例如,上面的代码也可以写成: ``` let squared = apply(numbers) { (number) -> Int in return number * number } ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值