美文网首页
swift5(7)闭包

swift5(7)闭包

作者: C_G__ | 来源:发表于2020-02-26 16:31 被阅读0次

感谢作者
https://www.jianshu.com/p/098d40b8bca5

        // Closures:闭包
        // 全局函数和嵌套函数实际上是闭包的特例。闭包采用以下三种形式之一:
        // 全局函数是具有名称但不捕获任何值的闭包。
        // 嵌套函数是具有名称并且可以从其封闭函数中捕获值的闭包。
        // Closure表达式是一种未命名的可以从周围的上下文中捕获值的闭包,用轻量级语法编写。
        
        // Swift的闭包表达式鼓励简洁,因此闭包具备:
        // 从上下文中推断参数和返回值类型
        // 单表达式闭包的隐式返回
        // 简洁的参数名称
        // 尾随闭包语法
        
        // 闭包表达式语法
        // { (parameters) -> <#returnType#> in <#statements#> }
        // 闭包表达式语法中的参数可以是输入输出参数,但不能具有默认值。
        // 可以使用变量(variadic)参数。元组也可以用作参数类型和返回类型。
        
        // 排序数组
        // 内联闭包
        // 对于内联闭包表达式,参数和返回类型写在花括号内,而不是在花括号外。
        // 闭包的方法体的开头由in关键字引入。这个关键字表示闭包的参数
        // 和返回类型的定义已经完成,闭包的方法体即将开始。
        let nms = ["Chris", "Alex", "Ewa", "Barry", "Daniella"];
        let newArray1 = nms.sorted(by: {(s1:String, s2:String) -> Bool in
            return s1 > s2;
        });
        // 因为字符串数组的排序
        // 所以参数类型可推导,省略参数类型
        let newArray2 = nms.sorted { (s1, s2) -> Bool in
            return s1 > s2;
        }
        // 单表达式 返回值类型推导,省略返回值类型
        let newArray3 = names.sorted(by: {s1,s2 in s1 > s2});
        // 简写参数名称
        // 简写参数名称,可通过名称$ 0,$ 1,$ 2等引用闭包参数的值。
        // 如果在闭包表达式中使用这些简写参数名称,则可以从闭包表达式中
        // 省略闭包的参数列表,并将通过函数类型推断简写的参数名称的数量和类型。
        // in关键字也可以省略。
        let newArray4 = names.sorted(by: {$0 > $1});
        // 操作符方法
        // 上面的闭包表达式实际上有一种更简短的方式来编写。
        // Swift的String类型将其大于运算符>的实现,定义为具有
        // 两个String类型参数的方法,并返回Bool类型的值。
        // 这与sorted(by :)方法所需的方法类型完全匹配。
        // 因此,可以简单地传入运算符>
        let newArray5 = names.sorted(by: >);
        print(newArray1); //!< ["Ewa", "Daniella", "Chris", "Barry", "Alex"]
        
        // 尾随闭包
        trailingClosures(parameter: "不是尾随闭包写法1", block: blockFunction);
        trailingClosures(parameter: "不是尾随闭包写法2", block: {(parameter:String)->Void in print(parameter);
        });
        trailingClosures(parameter: "不是尾随闭包写法3", block: {(parameter) in print(parameter);});
        //!< 参数类型和返回值可以根据函数类型得知,故可以省略
        //尾随闭包写法的调用形式,block函数标签不能出现在圆括号内
        trailingClosures(parameter: "尾随闭包的写法") { (parameter) in
            print(parameter);
        };
        // sorted(by :)的尾随闭包的写法
        let newArray6 = names.sorted(){s1,s2 in s1 > s2};
        let newArray7 = names.sorted(){$0>$1};
        let newArray8 = names.sorted{s1,s2 in s1 > s2};
        let newArray9 = names.sorted{$0>$1};

        // 值的捕获
        // increaseByTen其实是内部的嵌套函数(闭包的一种),
        // 捕获了`createIncrementer`方法的参数`amount`与方法体中定义的`total`变量。
        let increaseByTen = createIncrementer(forIncrese: 10);
        print(increaseByTen()); //!< log:10
        print(increaseByTen()); //!< log:20
        print(increaseByTen()); //!< log:30
        // 综上述`increaseByTen`函数捕获了捕获了`createIncrementer`方法的参数`amount`
        // 与方法体中定义的`total`变量,并在其内部持有了外部变量`total`和外部方法参数`amount`的副本。
        // 以至于`increaseByTen`可以每次调用都能基于`amount`的值,对变量`total`进行递增,
        // 并且返回结果。
        let increaseBySix = createIncrementer(forIncrese: 6)
        print(increaseBySix())//!< log:6
        print(increaseBySix())//!< log:12
        print(increaseBySix())//!< log:18
        // 综上述:`increaseBySix`是调用了`createIncrementer`生成的一个`()->Int`类型的常量。
        // 在生成的过程中,内部的闭包(嵌套函数)`increase`重新捕获了外部变量`total`
        // 和外部方法参数`amount`,并返回此方法赋值给了`increaseBySix`,
        // 以至于`increaseBySix`和`increaseByTen`具备不同的递增系数。
        // 本质上这是两个不同的函数类型的常量。
        
        // 闭包是引用类型
        // 函数和闭包是引用类型
        let alsoIncreaseByTen = increaseByTen; //!< 引用传递
        print(alsoIncreaseByTen()); //!< log:40
        let alsoIncreaseByTen1 = increaseByTen;
        print(alsoIncreaseByTen1()); //!< log:50
        
        // 逃逸闭包
        // 当一个函数需要用到异步操作回调的时候需要使用逃逸闭包。
        //调用
        escapeClosure.startEscape();
        //!< 场景1逃逸闭包1被调用了 场景2逃逸闭包2被调用了
        
        // 自动闭包:Autoclosures
        var nameArray = ["赵云","关羽","张飞","刘备"];
        //闭包参数为空 被省略 返回值是String类型由`nameArray.remove(at: 0)`的返回值决定 故省略,同时省略了`in`关键字
        let removeClosure = {
            nameArray.remove(at: 0);
        };
        print("调用`removeClosure`移除之前,数组`nameArray`的个数:\(nameArray.count)。调用`removeClosure`之后移除了字符串:\(removeClosure()) ,数组`nameArray`的个数变为:\(nameArray.count)。综上述可以看出自动闭包允许延迟调用,因为在调用闭包之前,内部代码不会运行");

        // 将闭包作为参数传递给函数时,在函数中进行数据元素移除的操作
        escapeClosure.unknownOperate { () -> String in
            nameArray.remove(at: 0);
        };
        // 更简化的形式
        escapeClosure.unknownOperate {nameArray.remove(at: 0)};
        // 调用很神奇啊,但也会让人很蒙 有木有
        escapeClosure.autoClosure(operation: nameArray.remove(at: 0));
        //调用
        escapeClosure.doAutoclosureAndEscape();
        //!< 自动闭包逃逸
        /*控制台输出:
        我是可逃逸的自动闭包:0号
        我是来自数组的可逃逸的自动闭包:1号
        */
class escapeClosure: NSObject {
    //声明一个闭包类型的数组
    var closureArray : [(String)->Void] = []
    override init() {
        super.init()
        
    }
    //模仿闭包逃逸:写完 closureArray.append编译器检测到时逃逸闭包提示添加@escaping
    func escapeClosures(title:String,handle:@escaping (String)->Void){
        closureArray.append(handle)
    }
    //类方法
    static func startEscape(){
       let escapeObject = escapeClosure()
       escapeObject.escapeClosures(title: "场景1") { (s1) in
            print("场景1"+s1)//!< 场景1逃逸闭包1被调用了
        }
        escapeObject.escapeClosures(title: "场景2") { (s1) in
            print("场景2"+s1)//!< 场景2逃逸闭包2被调用了
        }
        //使用迭代器进行下标和元素的同时遍历
        for (index,obj) in  escapeObject.closureArray.enumerated() {
            obj("逃逸闭包\(index+1)被调用了")
        }
    }
    
    // 延迟调用的另一种形式,定义个拟合自动闭包的函数类型作为参数的函数。
    // 先定义闭包,随后在函数体内调用获取值。
    static func unknownOperate(operation:()->String) -> Void {
        print("闭包作为参数,输出的删除的数组的字符串:\(operation())");
        //<!闭包作为参数,输出的删除的数组的字符串:赵云
    }
    //定义一个自动闭包的形式
    static func autoClosure(operation: @autoclosure ()->String){
        print("自动闭包作为参数,输出的删除的数组的字符串:\(operation())");
    }
    
    //定义存储自动闭包类型的数组变量
    var autoclosureArray : [()->String] = [];
    //自动闭包实现逃逸
    func autoclosureAndEscape(handle: @autoclosure @escaping ()->String) -> Void {
        autoclosureArray.append(handle);
    }
    //执行自动闭包逃逸操作
    static func doAutoclosureAndEscape(){
        var nameArray = ["我是来自数组的可逃逸的自动闭包"];
        //实例化对象
        let escapeObj = escapeClosure();
        escapeObj.autoclosureAndEscape(handle: "我是可逃逸的自动闭包");
        escapeObj.autoclosureAndEscape(handle: nameArray.remove(at: 0));
        //逃逸闭包的调用,在函数返回后
        for (index,handle) in escapeObj.autoclosureArray.enumerated() {
            print("\(handle()):\(index)号");
        }
    }
    
}

相关文章

  • swift5(7)闭包

    感谢作者https://www.jianshu.com/p/098d40b8bca5

  • Swift5 闭包及其应用

    关于如何理解闭包 学习闭包的第一个难点就是理解闭包,可能很多人用了很久的闭包都还不太清楚闭包到底是什么,我这里提供...

  • Swift5 函数与闭包

    函数 是一种特殊的闭包 内部函数 在函数体内部定义的函数,调用需在声明后 外部参数及忽略 提供外部参数能增强函数的...

  • swift5 基本语法-闭包

    在swift中,说到闭包表达式(Closure Expression),我们就能想起来Objective-C中的B...

  • Swift5.1闭包

    7.闭包 闭包表达式闭包表达式一般形式:{ (参数列表) -> 返回值类型 in statements...

  • Swift语法 Swift5 【07 - 闭包】

    作者: Liwx 邮箱: 1032282633@qq.com 源码: 需要源码的同学, 可以在评论区留下您的邮箱 ...

  • swift-闭包

    闭包 闭包定义 闭包简化 - 尾随闭包 闭包参数 闭包返回值 闭包的循环引用

  • 7_闭包

    Swift 的闭包表达式拥有简洁的风格,并鼓励在常见场景中进行语法优化,主要优化如下: 利用上下文推断参数和返回值...

  • #7 swift 闭包

    swift 中的闭包和JS中的匿名函数很像,但是它还有一些其它的特性,其中包括一些看起来很怪异的语法糖,写法看起来...

  • 7.闭包

    sort 函数 func backward(a:Int, b:Int) -> Bool { return a > ...

网友评论

      本文标题:swift5(7)闭包

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