Swift 逃逸闭包 && 非逃逸闭包

主要理解点 : @escaping关键字修饰的闭包类型改怎么用?怎么理解?

  • 逃逸闭包

当一个闭包作为参数传到一个函数中,但是这个闭包在函数返回之后才被执行,我们称该闭包从函数中逃逸. 当你定义接受闭包作为参数的函数时,你可以在参数名之前标注 @escaping,用来指明这个闭包是允许“逃逸”出这个函数的.

简单粗暴的理解 : 逃逸闭包就是把这个传入的block可以保存在外部.等待某一时刻你可以再次调用这个block.这一个时刻是在函数返回之后.

Demo测试
//一种能使闭包“逃逸”出函数的方法是,将这个闭包保存在一个函数外部定义的变量中。
//这里是一个闭包数组
typealias completionHandlerBlock = () -> Void
var completionHandlers: [completionHandlerBlock] = []


class SomeClass {
    var x = 10
    func doSomething() {
        someFunctionWith_Escaping_Closure { self.x = 200 }  //将一个闭包标记为 @escaping 意味着你必须在闭包中显式地引用 self。
        someFunctionWith_Non_Escaping_Closure { x = 200 }   //不带self
    }
    
    //逃逸闭包
    func someFunctionWith_Escaping_Closure(completionHandler: @escaping completionHandlerBlock) {
        //函数接受一个闭包作为参数,该闭包被添加到一个函数外定义的数组中。如果你不将这个参数标记为 @escaping,就会得到一个编译错误。
        completionHandlers.append(completionHandler)
    }
    
    //非逃逸闭包
    func someFunctionWith_Non_Escaping_Closure(closure: () -> Void) {
        //该闭包是一个非逃逸闭包,这意味着它可以隐式引用 self。同时无法保存在外部
        completionHandlers.append(closure)  //报错 : Passing non-escaping parameter 'closure' to function expecting an @escaping closure
        closure()
    }
}

方法调用 :

override func viewDidLoad() {
        super.viewDidLoad()
        let instance = SomeClass()
        
        instance.doSomething()
        print(instance.x) // 打印出 "200"
        
        completionHandlers.first?()
        print(instance.x) // 打印出 "100"
    }

参考学习 :
Swift编程 : 闭包(Closures)
极客学院 : 闭包(Closures)

你可能感兴趣的:(Swift 逃逸闭包 && 非逃逸闭包)