转载

浅谈iOS中的闭包(二) - Swift中的逃逸闭包与自动闭包

非逃逸闭包与逃逸闭包(Nonescaping Closures vs Escaping Closures)

当闭包作为函数的参数传入时,很有可能这个闭包在函数返回之后才会被执行,这就是逃逸闭包。

在Swift中可以在参数名前标注 @noescape 来指明这个闭包是不允许逃逸出这个函数的。因为非逃逸闭包只能在函数体中被执行,不能脱离函数体执行,所以这使得编译器可以明确的知道运行时的上下文环境,进而做出优化。

比如, sort(_:) 方法可以接受一个用于元素比较的闭包参数,它被指明为 @noescape ,因为排序结束后这个闭包就没用了。

一般情况下,一些异步函数会使用逃逸闭包。这类函数会在异步操作开始之后立刻返回,但是闭包直到异步操作结束后才会被调用。比如网络请求中处理服务器返回请求的闭包。在这种情况下,逃逸闭包就可以派上用场了。一个常见的例子如下:

varhandlers: [()->Void] = []  func functionWithEscapingClosure(handler: () -> Void){ truehandlers.append(handler) } 

因为编译器知晓非逃逸闭包的上下文环境,所以非逃逸闭包中可以不写 self

比如:

classA { truevarx truefunc doSometing{ truetruefunctionWithEscapingClosure{x=250} true} } 

自动闭包

自动闭包,顾名思义是一种自动创建的闭包,用于包装函数参数的表达式,可以说是一种简便语法。

自动闭包不接受任何参数,被调用时会返回被包装在其中的表达式的值。

自动闭包的好处之二是让你能够延迟求值,因为代码段不会被执行直到你调用这个闭包,这样你就可以控制代码什么时候执行。

var students =["A","B","C"]  letstudentsProvider ={ students.removeAtIndex(0) }  studentsProvider() 

尽管调用了 removeAtIndex() 方法,但是此时并不会执行,知道第三行调用了这个闭包方法。

这里注意 studentsProviderstudentsProvider() 二者的不同,前者的类型是 ()->String 指向了一个函数,后者的类型是 String

@autoclosure

当闭包作为函数参数时,可以将参数标记 @autoclosure 来接收自动闭包。 @autoclosure 暗含了非逃逸闭包的特性,如果你想让这个自动闭包具有逃逸的特性需要更改标记为 @autoclosure(escaping)

原文  http://iJack.pw/2016/03/01/Swift中的逃逸闭包与自动闭包/
正文到此结束
Loading...