美文网首页
Escaping and Nonescaping Closure

Escaping and Nonescaping Closure

作者: __Guan__ | 来源:发表于2017-03-28 00:21 被阅读122次

本文翻译自这里

函数与闭包在Swift中作为一等公民,可以存储,当作参数传递,并且把它们看待成其他的对象或者类型。通常我们将闭包当作发送API完成后的回调。

在Swift3中,当你将闭包当作一个函数的参数时,会有一个新的建议:编译器将闭包默认为non-escaping。下面看看non-escapingeascaping的区别。

Non-Escaping Closures

non-escaping的生命周期:

1.将闭包传递给函数
2.函数执行闭包(或不执行)
3.函数返回

non-escapingnon-escaping

这个闭包并没有“逃逸(escape)”到函数体外。当函数结束时,传递的闭包离开函数作用域,并且没有其他的引用指向该闭包。

如果考虑到内存的持有和释放平衡,这个闭包的引用计数在函数结束时和开始时是一样的。

Escaping Closures

现在可以猜到escaping closure是什么意思。在函数内,你可以一直运行闭包(或者不);这里有几种方法来让闭包逃逸出函数体:

  • 异步操作:如果在一个异步队列中执行闭包,那么这个队列会一直持有这个闭包。你无法确定闭包何时被执行,并且也无法保证在函数返回前结束闭包。

  • 存储:将闭包存储为全局变量、属性、或者任何其他的存储方式。

escapingescaping

Escaping and Non-Escaping in Swift 3

在Swift1和2中,闭包参数默认为escaping。如果能够确保闭包没有逃逸出函数体,你可以使用@noescape修饰它。

在Swift3中有些不同,参数闭包默认修饰为non-escaping

如果闭包修饰为non-escaping,这里有一些潜在的优化。因为闭包不会逃逸,编译器可以将闭包的存储和调用优化。

经常碰到的情况就是闭包中持有self的时候:

class ClassA {
     // takes a closure (non-escaping by default) 
     func someMethod(closure: () -> Void) {  
         // secret stuff 
    }
}
class ClassB { 
    let classA = ClassA() 
    var someProperty = "Hello" 
    
    func testClosure() {
         classA.someMethod {
            // self is captured! 
            someProperty = "Inside the closure!" 
        } 
    }
}

当调用someMethod的时候,记住somePropertyClassB的成员属性。只有闭包为逃逸闭包的时候才必须使用self,而这段代码在Swift3中运行不会有任何问题。
这个闭包仍然会截获self,但是因为闭包在函数结束后就会释放,所以编译器会知道没有发生循环引用。
如果将代码改成如下这样:

func someMethod(closure: @escaping () -> Void) {
     // secret stuff
}

现在这变成另外一种情况,当调用这个方法并且提供一个有引用指向的闭包,在闭包内必须明确使用self来提醒自己这个闭包截获了当前的self

最后

在Swift3中,闭包参数默认为non-escaping,根据自己的需求使用@escaping。非逃逸闭包当做参数传递时,在函数返回之前闭包必须执行完。

相关文章

  • Escaping and Nonescaping Closure

    本文翻译自这里 函数与闭包在Swift中作为一等公民,可以存储,当作参数传递,并且把它们看待成其他的对象或者类型。...

  • swift : Escaping closure capture

    Escaping closure captures non-escaping parameter 'complet...

  • iOS相关 | swift 闭包

    一、闭包分为:1.逃逸闭包(Escaping Closures)2.非逃逸闭包(Nonescaping Closu...

  • Swift中的闭包

    在Swift中有两种闭包,逃逸闭包(@escaping)和非逃逸闭包(@nonescaping)。从Swift 3...

  • 尝试理解Swift中的@escaping

    要理解@escaping,首先需要理解closure, 要理解closure,首先理解匿名函数。 先理解匿名函数 ...

  • Swift中的@escaping

    要理解@escaping,首先需要理解closure, 要理解closure,首先理解匿名函数。先理解匿名函数要在...

  • swift中在闭包内修改结构体的内容

    逃逸闭包不可 上面代码会报错:“Escaping closure captures mutating 'self'...

  • @escaping修饰block

    Escaping Closure=(逃逸闭包)如果一个闭包被作为一个参数传递给一个函数, 并且在函数return之...

  • Escaping Closures - Swift

    逃逸闭包和非逃逸闭包 逃逸闭包(escaping closure),什么是逃逸闭包?苹果官方给的定义是:当一个闭包...

  • swift 3.0 之@Never | @escaping

    @escaping Swift3,闭包参数默认为non-escaping,也可以使用@escaping属性关键字为...

网友评论

      本文标题:Escaping and Nonescaping Closure

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