Closures (闭包)

Closuresare self-contained blocks of functionality that can be passed around and used in your code. Closures in Swift are similar to blocks in C and Objective-C and to lambdas in other programming languages.

闭包是自包含的函数代码块,可以在代码中被传递和使用。Swift 中的闭包与 C 和 Objective-C 中的代码块(blocks)以及其他一些编程语言中的匿名函数比较相似。

Closures can capture and store references to any constants and variables from the context in which they are defined. This is known asclosing overthose constants and variables. Swift handles all of the memory management of capturing for you.

闭包可以捕获和存储其所在上下文中任意常量和变量的引用。被称为包裹常量和变量。 Swift 会为你管理在捕获过程中涉及到的所有内存操作。


Don’t worry if you are not familiar with the concept of capturing. It is explained in detail below inCapturing Values.


Global and nested functions, as introduced inFunctions, are actually special cases of closures. Closures take one of three forms:


1. Global functions are closures that have a name and do not capture any values.


2. Nested functions are closures that have a name and can capture values from their enclosing function.


3. Closure expressions are unnamed closures written in a lightweight syntax that can capture values from their surrounding context.


Swift’s closure expressions have a clean, clear style, with optimizations that encourage brief, clutter-free syntax in common scenarios. These optimizations include:

Swift 的闭包表达式拥有简洁的风格,并鼓励在常见场景中进行语法优化,主要优化如下:

1. Inferring parameter and return value types from context


2. Implicit returns from single-expression closures


3. Shorthand argument names


4. Trailing closure syntax


Closure Expressions (闭包表达式)

Nested functions, as introduced inNested Functions, are a convenient means of naming and defining self-contained blocks of code as part of a larger function. However, it is sometimes useful to write shorter versions of function-like constructs without a full declaration and name. This is particularly true when you work with functions or methods that take functions as one or more of their arguments.


Closure expressionsare a way to write inline closures in a brief, focused syntax. Closure expressions provide several syntax optimizations for writing closures in a shortened form without loss of clarity or intent. The closure expression examples below illustrate these optimizations by refining a single example of thesorted(by:)method over several iterations, each of which expresses the same functionality in a more succinct way.


The Sorted Method (sorted 方法)

Swift’s standard library provides a method calledsorted(by:), which sorts an array of values of a known type, based on the output of a sorting closure that you provide. Once it completes the sorting process, thesorted(by:)method returns a new array of the same type and size as the old one, with its elements in the correct sorted order. The original array is not modified by thesorted(by:)method.

Swift 标准库提供了名为sorted(by:)的方法,它会根据你所提供的用于排序的闭包函数将已知类型数组中的值进行排序。一旦排序完成,sorted(by:)方法会返回一个与原数组大小相同,包含同类型元素且元素已正确排序的新数组。原数组不会被sorted(by:)方法修改。

The closure expression examples below use thesorted(by:)method to sort an array ofStringvalues in reverse alphabetical order. Here’s the initial array to be sorted:


let names= ["Chris", "Alex", "Ewa", "Barry", "Daniella"]

Thesorted(by:)method accepts a closure that takes two arguments of the same type as the array’s contents, and returns aBoolvalue to say whether the first value should appear before or after the second value once the values are sorted. The sorting closure needs to returntrueif the first value should appearbeforethe second value, andfalseotherwise.


This example is sorting an array ofStringvalues, and so the sorting closure needs to be a function of type(String, String) -> Bool.

该例子对一个String类型的数组进行排序,因此排序闭包函数类型需为(String, String) -> Bool。

One way to provide the sorting closure is to write a normal function of the correct type, and to pass it in as an argument to thesorted(by:)method:


func backward (_s1:String,_s2:String) ->Bool{



var reversedNames = names.sorted(by:backward)

// reversedNames is equal to ["Ewa", "Daniella", "Chris", "Barry", "Alex"]

If the first string (s1) is greater than the second string (s2), thebackward(_:_:)function will returntrue, indicating thats1should appear befores2in the sorted array. For characters in strings, “greater than” means “appears later in the alphabet than”. This means that the letter"B"is “greater than” the letter"A", and the string"Tom"is greater than the string"Tim". This gives a reverse alphabetical sort, with"Barry"being placed before"Alex", and so on.


However, this is a rather long-winded way to write what is essentially a single-expression function (a > b). In this example, it would be preferable to write the sorting closure inline, using closure expression syntax.

然而,以这种方式来编写一个实际上很简单的表达式(a > b),确实太过繁琐了。对于这个例子来说,利用闭包表达式语法可以更好地构造一个内联排序闭包。

Closure Expression Syntax (闭包表达式语法)

Closure expression syntax has the following general form:


{ (parameters) ->return typein



Theparametersin closure expression syntax can be in-out parameters, but they can’t have a default value. Variadic parameters can be used if you name the variadic parameter. Tuples can also be used as parameter types and return types.

闭包表达式参数可以是 in-out 参数,但不能设定默认值。也可以使用具名的可变参数(译者注:但是如果可变参数不放在参数列表的最后一位的话,调用闭包的时时编译器将报错。可参考这里)。元组也可以作为参数和返回值。

The example below shows a closure expression version of thebackward(_:_:)function from earlier:


reversedNames = names.sorted(by: { (s1:String,s2:String) ->Boolin



Note that the declaration of parameters and return type for this inline closure is identical to the declaration from thebackward(_:_:)function. In both cases, it is written as(s1: String, s2: String) -> Bool. However, for the inline closure expression, the parameters and return type are writteninsidethe curly braces, not outside of them.

需要注意的是内联闭包参数和返回值类型声明与backward(_:_:)函数类型声明相同。在这两种方式中,都写成了(s1: String, s2: String) -> Bool。然而在内联闭包表达式中,函数和返回值类型都写在大括号内,而不是大括号外。

The start of the closure’s body is introduced by theinkeyword. This keyword indicates that the definition of the closure’s parameters and return type has finished, and the body of the closure is about to begin.


Because the body of the closure is so short, it can even be written on a single line:


reversedNames = names.sorted(by: { (s1:String,s2:String) ->Boolinreturns1>s2} )

This illustrates that the overall call to thesorted(by:)method has remained the same. A pair of parentheses still wrap the entire argument for the method. However, that argument is now an inline closure.


Inferring Type From Context (根据上下文推断类型)

Because the sorting closure is passed as an argument to a method, Swift can infer the types of its parameters and the type of the value it returns. Thesorted(by:)method is being called on an array of strings, so its argument must be a function of type(String, String) -> Bool. This means that the(String, String)andBooltypes do not need to be written as part of the closure expression’s definition. Because all of the types can be inferred, the return arrow (->) and the parentheses around the names of the parameters can also be omitted:

因为排序闭包函数是作为sorted(by:)方法的参数传入的,Swift 可以推断其参数和返回值的类型。sorted(by:)方法被一个字符串数组调用,因此其参数必须是(String, String) -> Bool类型的函数。这意味着(String, String)和Bool类型并不需要作为闭包表达式定义的一部分。因为所有的类型都可以被正确推断,返回箭头(->)和围绕在参数周围的括号也可以被省略:

reversedNames = names.sorted(by: {s1,s2inreturns1>s2} )

It is always possible to infer the parameter types and return type when passing a closure to a function or method as an inline closure expression. As a result, you never need to write an inline closure in its fullest form when the closure is used as a function or method argument.


Nonetheless, you can still make the types explicit if you wish, and doing so is encouraged if it avoids ambiguity for readers of your code. In the case of thesorted(by:)method, the purpose of the closure is clear from the fact that sorting is taking place, and it is safe for a reader to assume that the closure is likely to be working withStringvalues, because it is assisting with the sorting of an array of strings.


Implicit Returns from Single-Expression Closures (单表达式闭包隐式返回)

Single-expression closures can implicitly return the result of their single expression by omitting thereturnkeyword from their declaration, as in this version of the previous example:


reversedNames = names.sorted(by: {s1,s2ins1>s2} )

Here, the function type of thesorted(by:)method’s argument makes it clear that aBoolvalue must be returned by the closure. Because the closure’s body contains a single expression (s1 > s2) that returns aBoolvalue, there is no ambiguity, and thereturnkeyword can be omitted.

在这个例子中,sorted(by:)方法的参数类型明确了闭包必须返回一个Bool类型值。因为闭包函数体只包含了一个单一表达式(s1 > s2),该表达式返回Bool类型值,因此这里没有歧义,return关键字可以省略。

Shorthand Argument Names (参数名称缩写)

Swift automatically provides shorthand argument names to inline closures, which can be used to refer to the values of the closure’s arguments by the names$0,$1,$2, and so on.

Swift 自动为内联闭包提供了参数名称缩写功能,你可以直接通过$0,$1,$2来顺序调用闭包的参数,以此类推。

If you use these shorthand argument names within your closure expression, you can omit the closure’s argument list from its definition, and the number and type of the shorthand argument names will be inferred from the expected function type. Theinkeyword can also be omitted, because the closure expression is made up entirely of its body:


reversedNames = names.sorted(by: {$0>$1} )

Here,$0 and $1 refer to the closure’s first and secondStringarguments.


Operator Methods (运算符方法)

There’s actually an evenshorterway to write the closure expression above. Swift’sStringtype defines its string-specific implementation of the greater-than operator (>) as a method that has two parameters of typeString, and returns a value of typeBool. This exactly matches the method type needed by thesorted(by:)method. Therefore, you can simply pass in the greater-than operator, and Swift will infer that you want to use its string-specific implementation:

实际上还有一种更简短的方式来编写上面例子中的闭包表达式。Swift 的String类型定义了关于大于号(>)的字符串实现,其作为一个函数接受两个String类型的参数并返回Bool类型的值。而这正好与sorted(by:)方法的参数需要的函数类型相符合。因此,你可以简单地传递一个大于号,Swift 可以自动推断出你想使用大于号的字符串函数实现:

reversedNames = names.sorted(by: >)

For more about operator method, seeOperator Methods.


Trailing Closures (尾随闭包)

If you need to pass a closure expression to a function as the function’s final argument and the closure expression is long, it can be useful to write it as atrailing closureinstead. A trailing closure is written after the function call’s parentheses, even though it is still an argument to the function. When you use the trailing closure syntax, you don’t write the argument label for the closure as part of the function call.


func someFunctionThatTakesAClosure(closure: () ->Void) {

    // function body goes here


// Here's how you call this function without using a trailing closure:

// 以下是不使用尾随闭包进行函数调用

someFunctionThatTakesAClosure(closure: {

// closure's body goes here


// Here's how you call this function with a trailing closure instead:

// 以下是使用尾随闭包进行函数调用

someFunctionThatTakesAClosure() {

// trailing closure's body goes here

// 闭包主体部分


The string-sorting closure from theClosure Expression Syntaxsection above can be written outside of thesorted(by:)method’s parentheses as a trailing closure:


reversedNames = names.sorted() {$0>$1}

If a closure expression is provided as the function or method’s only argument and you provide that expression as a trailing closure, you do not need to write a pair of parentheses()after the function or method’s name when you call the function:


reversedNames = names.sorted{$0>$1}

Trailing closures are most useful when the closure is sufficiently long that it is not possible to write it inline on a single line. As an example, Swift’sArraytype has amap(_:)method which takes a closure expression as its single argument. The closure is called once for each item in the array, and returns an alternative mapped value (possibly of some other type) for that item. The nature of the mapping and the type of the returned value is left up to the closure to specify.

当闭包非常长以至于不能在一行中进行书写时,尾随闭包变得非常有用。举例来说,Swift 的Array类型有一个map(_:)方法,这个方法获取一个闭包表达式作为其唯一参数。该闭包函数会为数组中的每一个元素调用一次,并返回该元素所映射的值。具体的映射方式和返回值类型由闭包来指定。

After applying the provided closure to each array element, themap(_:)method returns a new array containing all of the new mapped values, in the same order as their corresponding values in the original array.


Here’s how you can use themap(_:)method with a trailing closure to convert an array ofIntvalues into an array ofStringvalues. The array[16, 58, 510]is used to create the new array["OneSix", "FiveEight", "FiveOneZero"]:

下例介绍了如何在map(_:)方法中使用尾随闭包将Int类型数组[16, 58, 510]转换为包含对应String类型的值的数组["OneSix", "FiveEight", "FiveOneZero"]:

let digitNames = [




let numbers= [16,58,510]

The code above creates a dictionary of mappings between the integer digits and English-language versions of their names. It also defines an array of integers, ready to be converted into strings.


You can now use thenumbersarray to create an array ofStringvalues, by passing a closure expression to the array’smap(_:)method as a trailing closure:



    (number) ->Stringin


    var output=""


  output=digitNames[number%10]! +output


} while number>0

   return output


// strings is inferred to be of type [String]

// strings 常量被推断为字符串类型数组,即 [String]

// its value is ["OneSix", "FiveEight", "FiveOneZero"]

Themap(_:)method calls the closure expression once for each item in the array. You do not need to specify the type of the closure’s input parameter,number, because the type can be inferred from the values in the array to be mapped.


In this example, the variablenumberis initialized with the value of the closure’snumberparameter, so that the value can be modified within the closure body. (The parameters to functions and closures are always constants.) The closure expression also specifies a return type ofString, to indicate the type that will be stored in the mapped output array.


The closure expression builds a string calledoutputeach time it is called. It calculates the last digit ofnumberby using the remainder operator (number % 10), and uses this digit to look up an appropriate string in thedigitNamesdictionary. The closure can be used to create a string representation of any integer greater than zero.

闭包表达式在每次被调用的时候创建了一个叫做output的字符串并返回。其使用求余运算符(number % 10)计算最后一位数字并利用digitNames字典获取所映射的字符串。这个闭包能够用于创建任意正整数的字符串表示。


The call to thedigitNamesdictionary’s subscript is followed by an exclamation mark (!), because dictionary subscripts return an optional value to indicate that the dictionary lookup can fail if the key does not exist. In the example above, it is guaranteed thatnumber % 10will always be a valid subscript key for thedigitNamesdictionary, and so an exclamation mark is used to force-unwrap theStringvalue stored in the subscript’s optional return value.

字典digitNames下标后跟着一个叹号(!),因为字典下标返回一个可选值(optional value),表明该键不存在时会查找失败。在上例中,由于可以确定number % 10总是digitNames字典的有效下标,因此叹号可以用于强制解包 (force-unwrap) 存储在下标的可选类型的返回值中的String类型的值。

The string retrieved from thedigitNamesdictionary is added to thefrontofoutput, effectively building a string version of the number in reverse. (The expressionnumber % 10gives a value of6for16,8for58, and0for510.)

从digitNames字典中获取的字符串被添加到output的前部,逆序建立了一个字符串版本的数字。(在表达式number % 10中,如果number为16,则返回6,58返回8,510返回0。)

Thenumbervariable is then divided by10. Because it is an integer, it is rounded down during the division, so16becomes1,58becomes5, and510becomes51.


The process is repeated untilnumberis equal to0, at which point theoutputstring is returned by the closure, and is added to the output array by themap(_:)method.

整个过程重复进行,直到number /= 10为0,这时闭包会将字符串output返回,而map(_:)方法则会将字符串添加到映射数组中。

The use of trailing closure syntax in the example above neatly encapsulates the closure’s functionality immediately after the function that closure supports, without needing to wrap the entire closure within themap(_:)method’s outer parentheses.


Capturing Values (值捕获)

A closure cancaptureconstants and variables from the surrounding context in which it is defined. The closure can then refer to and modify the values of those constants and variables from within its body, even if the original scope that defined the constants and variables no longer exists.


In Swift, the simplest form of a closure that can capture values is a nested function, written within the body of another function. A nested function can capture any of its outer function’s arguments and can also capture any constants and variables defined within the outer function.

Swift 中,可以捕获值的闭包的最简单形式是嵌套函数,也就是定义在其他函数的函数体内的函数。嵌套函数可以捕获其外部函数所有的参数以及定义的常量和变量。

Here’s an example of a function calledmakeIncrementer, which contains a nested function calledincrementer. The nestedincrementer()function captures two values,runningTotalandamount, from its surrounding context. After capturing these values,incrementeris returned bymakeIncrementeras a closure that incrementsrunningTotalbyamounteach time it is called.


func makeIncrementer(forIncrementamount:Int) -> () ->Int{

    var runningTotal=0

    func incrementer() ->Int{


        return runningTotal


return incrementer


The return type ofmakeIncrementeris() -> Int. This means that it returns afunction, rather than a simple value. The function it returns has no parameters, and returns anIntvalue each time it is called. To learn how functions can return other functions, seeFunction Types as Return Types.

makeIncrementer返回类型为() -> Int。这意味着其返回的是一个函数,而非一个简单类型的值。该函数在每次调用时不接受参数,只返回一个Int类型的值。关于函数返回其他函数的内容,请查看函数类型作为返回类型

ThemakeIncrementer(forIncrement:)function defines an integer variable calledrunningTotal, to store the current running total of the incrementer that will be returned. This variable is initialized with a value of0.


ThemakeIncrementer(forIncrement:)function has a singleIntparameter with an argument label offorIncrement, and a parameter name ofamount. The argument value passed to this parameter specifies how muchrunningTotalshould be incremented by each time the returned incrementer function is called. ThemakeIncrementerfunction defines a nested function calledincrementer, which performs the actual incrementing. This function simply addsamounttorunningTotal, and returns the result.


When considered in isolation, the nestedincrementer()function might seem unusual:


func incrementer() ->Int{


    return runningTotal


Theincrementer()function doesn’t have any parameters, and yet it refers torunningTotalandamountfrom within its function body. It does this by capturing areferencetorunningTotalandamountfrom the surrounding function and using them within its own function body. Capturing by reference ensures thatrunningTotalandamountdo not disappear when the call tomakeIncrementerends, and also ensures thatrunningTotalis available the next time theincrementerfunction is called.



As an optimization, Swift may instead capture and store acopyof a value if that value is not mutated by a closure, and if the value is not mutated after the closure is created.

为了优化,如果一个值不会被闭包改变,或者在闭包创建后不会改变,Swift 可能会改为捕获并保存一份对值的拷贝。

Swift also handles all memory management involved in disposing of variables when they are no longer needed.

Swift 也会负责被捕获变量的所有内存管理工作,包括释放不再需要的变量。

Here’s an example ofmakeIncrementerin action:


let incrementByTen = makeIncrementer(forIncrement:10)

This example sets a constant calledincrementByTento refer to an incrementer function that adds10to itsrunningTotalvariable each time it is called. Calling the function multiple times shows this behavior in action:


1. incrementByTen()

// returns a value of 10

2. incrementByTen()

// returns a value of 20

3. incrementByTen()

// returns a value of 30

If you create a second incrementer, it will have its own stored reference to a new, separaterunningTotalvariable:


let incrementBySeven = makeIncrementer(forIncrement:7)


// returns a value of 7

Calling the original incrementer (incrementByTen) again continues to increment its ownrunningTotalvariable, and does not affect the variable captured byincrementBySeven:



// returns a value of 40


If you assign a closure to a property of a class instance, and the closure captures that instance by referring to the instance or its members, you will create a strong reference cycle between the closure and the instance. Swift usescapture liststo break these strong reference cycles. For more information, seeStrong Reference Cycles for Closures.

如果你将闭包赋值给一个类实例的属性,并且该闭包通过访问该实例或其成员而捕获了该实例,你将在闭包和该实例间创建一个循环强引用。Swift 使用捕获列表来打破这种循环强引用。更多信息,请参考闭包引起的循环强引用

Closures Are Reference Types (闭包是引用类型)

In the example above,incrementBySevenandincrementByTenare constants, but the closures these constants refer to are still able to increment therunningTotalvariables that they have captured. This is because functions and closures arereference types.


Whenever you assign a function or a closure to a constant or a variable, you are actually setting that constant or variable to be areferenceto the function or closure. In the example above, it is the choice of closure thatincrementByTenrefers tothat is constant, and not the contents of the closure itself.


This also means that if you assign a closure to two different constants or variables, both of those constants or variables will refer to the same closure:


let alsoIncrementByTen = incrementByTen


// returns a value of 50

Escaping Closures (逃逸闭包)

A closure is said toescapea function when the closure is passed as an argument to the function, but is called after the function returns. When you declare a function that takes a closure as one of its parameters, you can write@escapingbefore the parameter’s type to indicate that the closure is allowed to escape.


One way that a closure can escape is by being stored in a variable that is defined outside the function. As an example, many functions that start an asynchronous operation take a closure argument as a completion handler. The function returns after it starts the operation, but the closure isn’t called until the operation is completed—the closure needs to escape, to be called later. For example:

一种能使闭包“逃逸”出函数的方法是,将这个闭包保存在一个函数外部定义的变量中。举个例子,很多启动异步操作的函数接受一个闭包参数作为 completion handler。这类函数会在异步操作开始之后立刻返回,但是闭包直到异步操作结束后才会被调用。在这种情况下,闭包需要“逃逸”出函数,因为闭包需要在函数返回之后被调用。例如:

var completionHandlers: [() ->Void] = []

    func someFunctionWithEscapingClosure(completionHandler: @escaping() ->Void) {



ThesomeFunctionWithEscapingClosure(_:)function takes a closure as its argument and adds it to an array that’s declared outside the function. If you didn’t mark the parameter of this function with@escaping, you would get a compiler error.


Marking a closure with@escapingmeans you have to refer toselfexplicitly within the closure. For example, in the code below, the closure passed tosomeFunctionWithEscapingClosure(_:)is an escaping closure, which means it needs to refer toselfexplicitly. In contrast, the closure passed tosomeFunctionWithNonescapingClosure(_:)is a nonescaping closure, which means it can refer toselfimplicitly.


func someFunctionWithNonescapingClosure(closure: () ->Void) {




  var x=10

  func doSomething() {





let instance=SomeClass()



// Prints "200"



// Prints "100"

Autoclosures (自动闭包)

Anautoclosureis a closure that is automatically created to wrap an expression that’s being passed as an argument to a function. It doesn’t take any arguments, and when it’s called, it returns the value of the expression that’s wrapped inside of it. This syntactic convenience lets you omit braces around a function’s parameter by writing a normal expression instead of an explicit closure.


It’s common tocallfunctions that take autoclosures, but it’s not common toimplementthat kind of function. For example, theassert(condition:message:file:line:)function takes an autoclosure for itsconditionandmessageparameters; itsconditionparameter is evaluated only in debug builds and itsmessageparameter is evaluated only ifconditionisfalse.

我们经常会调用采用自动闭包的函数,但是很少去实现这样的函数。举个例子来说,assert(condition:message:file:line:)函数接受自动闭包作为它的condition参数和message参数;它的condition参数仅会在 debug 模式下被求值,它的message参数仅当condition参数为false时被计算求值。

An autoclosure lets you delay evaluation, because the code inside isn’t run until you call the closure. Delaying evaluation is useful for code that has side effects or is computationally expensive, because it lets you control when that code is evaluated. The code below shows how a closure delays evaluation.

自动闭包让你能够延迟求值,因为直到你调用这个闭包,代码段才会被执行。延迟求值对于那些有副作用(Side Effect)和高计算成本的代码来说是很有益处的,因为它使得你能控制代码的执行时机。下面的代码展示了闭包如何延时求值。

var customersInLine= ["Chris","Alex","Ewa","Barry","Daniella"]


// Prints "5"

let customerProvider= {customersInLine.remove(at:0) }


// Prints "5"

print("Now serving\(customerProvider())!")

// Prints "Now serving Chris!"


// Prints "4"

Even though the first element of thecustomersInLinearray is removed by the code inside the closure, the array element isn’t removed until the closure is actually called. If the closure is never called, the expression inside the closure is never evaluated, which means the array element is never removed. Note that the type ofcustomerProvideris notStringbut() -> String—a function with no parameters that returns a string.

尽管在闭包的代码中,customersInLine的第一个元素被移除了,不过在闭包被调用之前,这个元素是不会被移除的。如果这个闭包永远不被调用,那么在闭包里面的表达式将永远不会执行,那意味着列表中的元素永远不会被移除。请注意,customerProvider的类型不是String,而是() -> String,一个没有参数且返回值为String的函数。

You get the same behavior of delayed evaluation when you pass a closure as an argument to a function.


// customersInLine is ["Alex", "Ewa", "Barry", "Daniella"]

func serve(customercustomerProvider: () ->String) {

    print("Now serving\(customerProvider())!")


serve(customer: {customersInLine.remove(at:0) } )

// Prints "Now serving Alex!"

Theserve(customer:)function in the listing above takes an explicit closure that returns a customer’s name. The version ofserve(customer:)below performs the same operation but, instead of taking an explicit closure, it takes an autoclosure by marking its parameter’s type with the@autoclosureattribute. Now you can call the function as if it took aStringargument instead of a closure. The argument is automatically converted to a closure, because thecustomerProviderparameter’s type is marked with the@autoclosureattribute.


// customersInLine is ["Ewa", "Barry", "Daniella"]

func serve(customercustomerProvider: @autoclosure() ->String) {

    print("Now serving\(customerProvider())!")



// Prints "Now serving Ewa!"


Overusing autoclosures can make your code hard to understand. The context and function name should make it clear that evaluation is being deferred.


If you want an autoclosure that is allowed to escape, use both the@autoclosureand@escapingattributes. The@escapingattribute is described above inEscaping Closures.


// customersInLine is ["Barry", "Daniella"]

var customerProviders: [() ->String] = []

func collectCustomerProviders(_customerProvider: @autoclosure@escaping() ->String) {






// Prints "Collected 2 closures."

forc ustomerProviderincustomerProviders{

    print("Now serving\(customerProvider())!")


// Prints "Now serving Barry!"

// Prints "Now serving Daniella!"

In the code above, instead of calling the closure passed to it as itscustomerProviderargument, thecollectCustomerProviders(_:)function appends the closure to thecustomerProvidersarray. The array is declared outside the scope of the function, which means the closures in the array can be executed after the function returns. As a result, the value of thecustomerProviderargument must be allowed to escape the function’s scope.



  • 以下翻译自Apple官方文档,结合自己的理解记录下来。翻译基于 swift 3.0.1 原文地址 Closure...
    艺术农阅读 468评论 0 3
  • 闭包 Closures are self-contained blocks of functionality th...
    peterchen阅读 229评论 0 2
  • 人生不易,挚友难得。白驹过隙间,身边只剩下可以彼此寒暄的朋友,真心又何其难寻,能让你捧腹大笑、吐诉真心的老友,各自...
    狐心雪阅读 17评论 0 0
  • 今天复盘总结下半年的第一个月,七月读过的书籍。 一、《聚焦:决定企业的未来》 艾·里斯著 特劳特定位系列的书籍,读...
    王建设自媒体阅读 95评论 0 2
  • 此刻,舒岩正在用他那诗人的眼睛透过劣质镜片望着那辆车,也望着这个畸形的世界。 接下这个生意后,他错过了一次绝佳的机...
    静石阅读 54评论 0 1