美文网首页
swift闭包(上) - 基本语法介绍

swift闭包(上) - 基本语法介绍

作者: SwiftDev | 来源:发表于2019-08-07 08:14 被阅读0次

    swift中的闭包是一个函数代码块,可以被传递和引用;跟OC中的Block很相似,
    闭包的定义:

    {
      (形参类表) -> (返回值)in
      函数体
    }
    

    代码:

    {
      (num1: Int, num2: Int) -> Int in
      return num1 + num2
    }
    

    两个参数 返回值为两个参数之和的一个闭包;

    我们定义一个闭包变量:

    var closures: (_ age: Int, _ height: Int) -> Int
    // 也可以不带参数标签
    var closure1: (Int, Int) -> Int
    

    拿个官方的例子简单使用一下闭包,看下面代码:

    var nameArray = ["jack", "rose", "john"]
    // 实用sort函数对数组进行排序
    // nameArray.sort(by: <(String, String) throws -> Bool>)
    // 可以看出sort函数需要的是一个 两个String参数,返回值是bool的闭包
    // 我们创建一个这样的闭包,传入进去,如下
    let sortClosure = {
      (s1: String, s2: String) -> Bool in
      // 放在sort函数中的含义就是,哪个值小,谁就在前面
      return s1 < s2
    }
    nameArray.sort(by: sortClosure)
    
    // result: jack、john、rose
    for i in nameArray {
      print(i)
    }
    

    当然官方还接介绍了其他的写法,例如:

    // 跟这句完全等价:nameArray.sort(by: sortClosure)
    nameArray.sort(by: <)
    

    我们这里就不多做赘述,就是一些简写的方法,开发中不常用,因为可读性太差,了解即可

    尾随闭包

    这个也是closures的简写,这个写法在实际开发中使用频繁

    // 定义了一个参数为闭包类型的函数
    func testClosures(closers: (_ age: Int)-> Void) { }
    // 调用该函数
    // 写法1. 完整的写法:
    testClosures(closers: {
       (age: Int) -> Void in
       print(age)
    })
    // 写法2. 为了提高代码的可读性,也可以这样写
    // 区别:参数标签可以省略,括号提前结束
    testClosures() {
       (age: Int) -> Void in
       print(age)
    }
    

    使用尾随闭包的条件:closures作为函数体的最后一个参数
    针对上面例子,如果函数只有一个参数,且为闭包作为参数的话,还可以把括号省略

    // 写法3
    testClosures { (age) in
    }
    

    在日常开发中,经常使用,例如网络请求基本都是这种写法
    //多个参数也一样,只是没有了写法3

    // 函数定义
    func testClosures(age: Int , closers: (_ age: Int)-> Void) { }
    // 调用
    testClosures(age: 10) { (age) in
    
    }
    

    逃逸闭包

    当一个闭包作为参数传到一个函数中,但是这个闭包在函数返回之后才被执行,我们称该闭包从函数中逃逸
    这是官方翻译,还是直接看代码比较好理解

    var complations: [() -> Void] = []
        
    func someFunctions(param: ()-> Void) {
      complations.append(param)
    }
    

    这段代码是编译不过的,因为最后一个闭包参数,是在是在函数执行完成之后,才可能会被执行,这种情况要加上关键字@escaping去修饰这个闭包参数,代表这个闭包可能要在函数结束后,才会执行这个闭包

    var complations: [() -> Void] = []
        
    func someFunctions(param: @escaping ()-> Void) {
      complations.append(param)
    }
    

    这样就可以正常使用,逃逸闭包网络请求中经常遇到

    自动闭包

    在实际开发中使用不多,了解这种写法。能看懂这种写法即可
    先看个例子:

    let resultClo = { 2+3 }
    // 完整写法:
    /*
    { () -> Int in
       return 2 + 3
    }
    */
    

    resultClo这就是一个自动闭包
    自动闭包格式固定只支持:() -> T 这种格式的闭包
    为什么要这样写,直接写上表达式let resultClo = 2+3不更简单吗?
    自动闭包可以延迟求值,需要的时候在取调用闭包resultClo(),得到表达式的值
    @autoclosure
    这个关键字会自动将一个表达式转换成闭包:

    func serve(customer customerPrivoder: @autoclosure () -> String) {
      print(customerPrivoder())
    }
    // 调用
    serve(customer: "jack")
    

    使用了 @autoclosure 修饰函数参数,在调用的时候只需要传入一个String就行,因为他会把 "jack" => {"jack"}

    tips:如果自己在实际开发中使用了 @autoclosure 最好明确写明注释,这个闭包会被延迟调用
    苹果官方的一些使用自动闭包的地方:
    我们常用的断言函数就使用了自动闭包,看下他的定义:

    public func assert(_ condition: @autoclosure () -> Bool, _ message: @autoclosure () -> String = String(), file: StaticString = #file, line: UInt = #line)
    

    函数接受自动闭包作为它的 condition 参数和 message 参数;它的 condition 参数仅会在 debug 模式下被求值,它的 message 参数仅当 condition 参数为 false 时被计算求值。

    空和运算符 ?? 也是使用了@autoclosure技术

    闭包的基本语法就梳理完成了,下篇会写一下闭包的内存管理和捕获等相关知识点

    相关文章

      网友评论

          本文标题:swift闭包(上) - 基本语法介绍

          本文链接:https://www.haomeiwen.com/subject/iodndctx.html