美文网首页
Swift中的闭包

Swift中的闭包

作者: 下班不写程序 | 来源:发表于2019-10-08 10:29 被阅读0次

1.可以理解成OC 中使用的block,但是本质不一样.
2.Swift中使用的是 闭包.
3.闭包是一个代码块.
4.在我们需要的时候执行.
5.闭包可以作为 参数 或者 返回值.
6.闭包内 使用self 注意 循环引用.
7.将“函数、函数指针、闭包”三者对比起来理解,能加深对闭包的理解:
函数: 具有特定功能的代码块;
函数指针: 指向函数的指针;
闭包:除具备“函数和函数指针”的所有功能外, 还包括声明它的上下文(如作用域内的自由变量等).

接下来的闭包定义都是参照函数的定义方式类比下来的, 便于记忆理解.

1.无参数 无返回值的闭包

    // 无参数 无返回值的函数
    func demoA1(){
        
        func sum(){
            print("无参数 无返回值的函数")
        }
        // 函数的调用 : 函数名()
        sum()
    }
    
    // 注意: 闭包就是 代码块 也就是{}, 用一个名称来记录它
    let closure1 = {}
    // 通过自动推导可以得出, 上面的常量closure 的类型为 ()->(), 因次得出:
    // 闭包的类型 是 ()->(), 前一个括号里面代表所需要的参数, 后一个括弧里面代表返回值
    // 也就是正常的闭包格式: let closure1: ()->() = {}
    // 在无参数无返回值的闭包里面 ()-()可以省略不写
    // 重点: 因为闭包是代码块, 因此所有的东西都要写在块里面, 这也是与函数的写法的区别!!!
    
    // 类比上面的函数来定义 -> 无参数无返回值的闭包
    func demoA2(){
        
        let closure = {()->() in
            print("无参数无返回值的闭包")
        }
        // 闭包的调用
        closure()
    }

2.有参数 无返回值的闭包

    // 有参数 无返回值的函数
    func demoB1(){
        
        func sum(a: Int){
            print(a)
        }
        // 函数的调用 : 函数名()
        sum(a: 8)
    }
    
    // 注意: 因为闭包是代码块, 因此所有的东西都要写在块里面, 这也是与函数的写法的区别!!!
    // 规则: 当将闭包的参数或返回值写在块里面的同时, 需要在返回值后面添加 in 来把闭包的参数或者返回值 与 闭包内部的逻辑隔开
    // 格式: let closure = {()->() in 闭包内部的代码逻辑}
    // 类比上面的函数来定义 -> 有参数无返回值的闭包
    func demoB2(){
        
        let closure = {(a: Int)->() in
            print(a)
        }
        // 闭包的调用
        closure(3)
    }
    
    // 同时, 仿照有参数 无返回值的函数, 有参数无返回值的闭包还有两种写法
    func demoB3(){
        
        let closure = {(a: Int)->Void in
            print(a)
        }
        // 闭包的调用
        closure(3)
    }
    // 或者 -- 这是最正常的,也是最多的一种写法
    func demoB4(){
        
        let closure = {(a: Int) in
            print(a)
        }
        // 闭包的调用
        closure(3)
    }

3.有参数 有返回值的闭包

    // 有参数 有返回值的函数
    func demoC1(){
        
        func sum(a: Int, b: Int) -> Int{
            return a + b
        }
        // 函数的调用 : 函数名()
        let result = sum(a: 3, b: 8)
        print(result)
    }
    
    // 类比上面的函数来定义 -> 有参数有返回值的闭包
    func demoC2(){
        
        let closure = {(a: Int, b: Int) -> Int in
            return a + b
        }
        // 闭包的调用
        let result = closure(9, 9)
        print(result)
    }

4. 总结: 闭包的格式 闭包定义的格式总结

5.闭包的实际演练(模拟加载数据)

5.1 传递的数据做闭包的参数还是返回值?
    /*
     1. 情景分析: 模拟加载数据, 当数据加载完成时, 传递数据显示到界面, 而不是一直等待, 体现闭包: 使用的时候才加载的特性, 不需要一直等待.
     2. 思考? 传递数据的时候, 数据是作为闭包的参数, 还是返回值???
    
     分析: 当传递的数据作为返回值,
     2.1 声明
     let closure = { (a: Int) -> Int in
        return a
     }
     
     2.2 调用
     let result = closure(5)
     
     2.3 结果分析
     这就相当于 在我传入5的时候得到5, 这不是自己在和自己玩嘛, 我已经是几了, 还调用一下干嘛...再说是外界需要这个数据, 我只是在加载而已, 所以传递的数据做为返回值根本不能满足对外界传递数据的需要.
     
     2.4 结论: 所以传递的数据要作为闭包的参数!
     */
5.2 闭包作为函数参数的写法和使用步骤
    /* 写法:
     模拟 OC 函数的参数的写法, 实现 Swift 中函数参数的书写
     :(int) a   OC中正常的数据类型做为参数的写法;
     a: Int     Swift中正常的数据类型作为参数的写法;
     a: ()->()  Swift中闭包作为参数的写法
     注意: 当闭包(()->())作为参数的时候,  两个小括弧里面只写上数据类型即可.
     */
    
    /* 使用步骤: 3步
     1. 在 需要得到数据 的地方 定义和实例化闭包.
     2. 在 能够得到数据 的地方, 得到数据的时候, 调用闭包.
     3. 在闭包的 块的作用域 中, 得到闭包回调的结果.
     */
5.3 模拟代码
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        // 1. 在想要得到数据的地方, 定义和实例化闭包
        let closure = {(result: String) -> () in
            // 3. 得到闭包回调的结果
            print(result) // 运行之后, 延迟2面, 打印:不想睡
        }
        
        loadData(callBack: closure)
    }
    
    // 模拟加载数据
    func loadData(callBack: @escaping (String) -> ()){
        // 子线程异步加载数据
        DispatchQueue.global().async {
            // 模拟消耗时间
            Thread.sleep(forTimeInterval: 2.0)
            // 模拟请求回来的数据, 要传递给viewDidLoad中使用
            let data = "不想睡"
            // 回到主线程, 刷新页面
            DispatchQueue.main.async {
                // 2. 在得到数据的时候,执行闭包
                callBack(data)
            }
        }
    }
5.4 @escaping关键字
    /*
     1. 在上一段模拟代码中, 我们发现一个修饰闭包的关键字, @escaping.
     2. 不必过度关注, 一般情况下Xcode会自动提示添加该关键字.
     3. @escaping的使用时机:
        3.1 闭包在其他线程执行 (上一段代码就是在其他线程执行了闭包)
        3.2 对传入的闭包进行了赋值操作(包括定义一个新的变量/常量来记录该闭包的时候, 见下面代码)
     */
    func loadData(callBack:@escaping (String) -> ()){
        
        let clo = callBack
        clo("@escaping关键字")
    }
5.5 @escaping关键字 更新一波

\color{red}{ 在swift5.0之后, 只有闭包在其他线程执行时才需要添加该关键字, 且Xcode会报错, 但不再有自动提示添加该关键字的功能 }

6.尾随闭包

就是系统的简写方式,了解即可. 以下两种情况为尾随闭包.

条件1: 定义的函数有且只有一个参数, 并且参数是闭包,函数调用时,( )可以省略.

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        // 1.0 正常写法
        let closure = { (result: String) in
            
        }
        loadData(callback: closure)
        // 1.1 可以演变成
        loadData(callback:  { (result: String) in
            
        })
        
        // 2.0 尾随闭包写法: 直接写loadData方法, 按回车,自动联想, 原理是->()和里面的参数名称可以省略, 参数类型也可以省略
        loadData { (result) in
            
        }
    }
    
    func loadData(callback: (String)->()){
        
    }

条件2: 定义的函数有多个参数, 但是最后一个参数为闭包 , 函数的( )提前关闭.

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        // 1.0 正常写法
        let closure = { (result: String) in
            
        }
        loadData(a: 3, b: "8", callback: closure)
        // 1.1 可以演变成
        loadData(a: 3, b: "8", callback: { (result: String) in
            
        })
        
        // 2.0 尾随闭包写法: 直接写loadData方法, 按回车,自动联想, 原理是->()里面的参数名称可以省略, ()提前闭合, 只留下闭包了,闭包的参数类型也可以省略
        loadData(a: 3, b: "8") { (result) in
            
        }
    }
    
    func loadData(a: Int, b: String, callback: (String)->()){
        
    }

相关文章

  • Swift-闭包

    Swift 闭包 函数 ()->() Swift 中的闭包和 Objective-C 中的 block 类似,闭包...

  • Swift闭包和函数

    函数在Swift中只是一种特殊的闭包,闭包在Swift语言中是一等公民,支持闭包嵌套和闭包传递。Swift中的闭包...

  • swift4 闭包

    swift 闭包 闭包:swift 中 函数是闭包的一种类似于oc的闭包闭包表达式(匿名函数) -- 能够捕获上下...

  • Swift学习笔记(1)

    SWift学习笔记 闭包 闭包表达式 闭包是自包含的函数代码块,可以在代码中被传递和使用。Swift 中的闭包与 ...

  • swift中的闭包

    swift中的闭包 闭包是自包含的函数代码块,可以在代码中被传递和使用。swift中的闭包与C和Objective...

  • Swift总结

    1.闭包 swift中的闭包类似于oc中的block回调,但是swift的闭包有很多种写法,具有多变性,今天就来总...

  • swift 闭包(闭包表达式、尾随闭包、逃逸闭包、自动闭包)

    闭包是自含的函数代码块,可以在代码中被传递和使用 闭包和swift的对比 Swift 中闭包与OC的 block ...

  • 闭包

    闭包 本节内容包括: 闭包表达式 尾随闭包 值捕获 闭包是引用类型 Swift 中的闭包与 C 和 Objecti...

  • Swift入门基础5——闭包

    何为闭包? Swift中的闭包和OC中的block很相似(其实也有其他语言有闭包的概念)。所谓闭包,就是可以捕获其...

  • swift学习笔记 ⑥ —— 闭包

    Swift学习笔记 - 文集 闭包,就是能够读取其他函数内部变量的函数。Swift 中的闭包与 C 和 OC 中的...

网友评论

      本文标题:Swift中的闭包

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