美文网首页待处理
Swift-闭包Closure

Swift-闭包Closure

作者: 守护地中海的花 | 来源:发表于2020-11-18 15:51 被阅读0次

    先复习一下函数Swift-func

    闭包可以定义一个函数

    闭包可以定义一个函数

    闭包可以定义一个函数

    闭包概念:

    • 一个函数和它所捕获的变量/常量环境组合起来,称为闭包
    • 一般指定义在函数内部的函数
    • 一般它捕获的是外层函数的局部变量/常量

    演绎过程:

    typealias Fn = (Int) -> Int
    func getFn() -> Fn {
        var num = 10
        func plus(i: Int) -> Int {
            num += I
            return num
        }
        return plus//这是函数哦 不能是实现
        return plus(I:)
    }
    
    var fnx = getFn()
    print(fnx(1))
    
    • 2层函数 外层函数getFn返回值是函数类型 内层函数plus也要返回函数类型
    • plus函数和num形成了闭包

    简易一下程序

    func getFn() -> Fn {
        var num = 10
        return {
            num += $0
            return num
        }
    }
    

    类比一个类的实例对象

    • 内存在堆空间
    • 捕获的局部变量/常量就是对象的成员(存储属性)
    • 组成闭包的函数 就是类内部定义的方法
    class Closure {
        var num = 0
        func plus(_ i:Int) -> Int {
            num += I
            return num
        }
    }
    var cs1 = Closure()
    print(cs1.plus(1))
    

    闭包

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

    func add(_ v1: Int,_ v2: Int) -> Int {
        v1 + v2
    }
    var fx = {
        (v1: Int,v2: Int) -> Int in
        return v1 + v2
    }
    print(fx(10,20))
    print(fx)
    print(add)
    
    把实现带着随便测试
    var fx1 = {
        (v1: Int,v2: Int) -> Int in
        return v1 + v2
    }(10,10)
    print(fx1)
    
    • 上面打印fx 打印结果: (Function)
    • 上面打印add 打印结果: (Function)
    • 闭包类似add 然后调用它 传入参数fx(10,20)
    image.png

    闭包作为参数(闭包简写真特么简 其实不简写容易读)

    //exec定义
    func exec(v1: Int,v2: Int,fn:(Int,Int) -> Int) {
        print(fn(v1,v2))
    }
    

    实现exec方法

    • 普通函数
    var fn:(Int,Int)->Int = add
    exec(v1: 10, v2: 10, fn: fn)
    
    • 闭包
    //写全一点
    exec(v1: 10, v2: 20, fn: {
        (v1: Int,v2: Int) -> Int in
        return v1 + v2
    })
    //省略return
    exec(v1: 10, v2: 20, fn: {
        (v1: Int,v2: Int) -> Int in
        v1 + v2
    })
    //省略参数
    exec(v1: 10, v2: 20, fn: {
        v1,v2 -> Int in
        v1 + v2
    })
    //省略返回值
    exec(v1: 10, v2: 20, fn: {
        v1,v2  in
        v1 + v2
    })
    //下标
    exec(v1: 10, v2: 10, fn: {
        $0 + $1
    })
    //一步到位了靠
    exec(v1: 10, v2: 10, fn: +)
    

    尾随闭包

    • 如果将一个很长的闭包表达式作为函数的最后一个实参,使用尾随闭包可以增强函数的可读性
    • 尾随闭包是一个被书写在函数调用括号外面(后面)的闭包表达式
    • 如果闭包表达式是函数的唯一实参,而且使用了尾随闭包的语法,那就不需要在函数名后面写圆括号
    func exec1(fn:(Int,Int) -> Int) {
        print(fn(1,2))
    }
    exec1(fn: {
        (v1: Int,v2: Int) -> Int in
        return v1 * v2
    })
    exec1{
        (v1: Int,v2: Int) -> Int in
        return v1 * v2
    }
    ......下面同样可以省略 自己搞吧
    

    自动闭包(语法真鸡贼)

    后面在搞吧 语法真特么难懂太简易了

    • @autoclosure 会自动将20 封装成闭包{20}
    • @autoclosure 只支持 () -> T 格式的参数
    • @autoclosure 并非只支持最后一个参数
    • 空合并运算符?? 使用了@autoclosure技术
    • 有@autoclosure 无@autoclosure,构成了函数重载
    • 为了避免与期望冲突,使用了@autoclosure的地方最好明确注释清楚,这个值会被推迟执行
    func getFirstPositive (_ v1: Int,_ v2: Int) -> Int {
        return v1 > 0 ?v1 : v2
    }
    print(getFirstPositive(10, 20))
    print(getFirstPositive(-2, 20))
    print(getFirstPositive(0, -4))
    //改成函数类型的参数,可以让v2延迟加载
    func getFirstPositive(_ v1: Int,_ v2: () -> Int) -> Int? {
        return v1 > 0 ? v1: v2()
    }
    print(getFirstPositive(-4, {20})!)
    
    func getFirstPositive1(_ v1: Int,_ v2:@autoclosure () -> Int) -> Int? {
        return v1 > 0 ? v1: v2()
    }
    print(getFirstPositive1(-4, 20)!)
    

    参数修饰符保持一致

    //如果返回值是函数类型,那么参数的修饰要保持统一
    func total(_ num: Int) -> (inout Int) -> Void {
        func plus(v: inout Int) {
            v += num
        }
        return plus
    }
    var vvvv = 5
    total(20)(&vvvv)
    print(vvvv)
    

    忽略参数(语法真鸡贼)

    func exec2(fn:(Int ,Int) -> Int) {
        print(fn(1,2))
    }
    exec2{_,_ in 100}
    

    练习

    var functions:[() -> Int] = []
    for i in 1...3 {
        functions.append{I}
    }
    for i in functions {
        print(i)
    }
    class Closure2 {
        var i: Int
        init(_ i: Int) {
            self.i = I
        }
        func get() -> Int {
            return I
        }
    }
    var clses:[Closure2] = []
    for i in 1...3 {
        clses.append(Closure2(i))
    }
    for i in clses {
        print(i.get())
    }
    

    补充案例

    案例一:网络请求 省略参数 逃逸闭包

    image.png

    Function types cannot have argument labels; use '_' before 'result'
    从Swift3.0开始, 苹果官方建议方法中函数类型的参数不要带参数名称, 尤其是不能带外部参数名.
    解决方案:

    • 省略标签参数
    • 这个闭包里面的标签参数是为了增加代码可读性
    class func requestData(parameters: [String:Any]?,finishedCallBack:(_ result:Any)->()) {
        finishedCallBack("回调请求内容")
    }
    

    新的问题


    image.png

    逃逸闭包捕获非逃逸闭包
    captures:捕获
    Escaping:逃逸


    image.png

    语法小计

    • 闭包实现 可以把参数省略
    NetworkTools.requestData(url: requestUrl, method: .post, parameters: parameters) { response, status in
        
    }
    NetworkTools.requestData(url: requestUrl, method: .post, parameters: parameters) { (response, status) in
        
    }
    

    相关文章

      网友评论

        本文标题:Swift-闭包Closure

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