Swift 3.1(7) Closures

来源:互联网 发布:mac平台chm制作软件 编辑:程序博客网 时间:2024/05/20 09:44

文档地址:

https://developer.apple.com/library/prerelease/content/documentation/Swift/Conceptual/Swift_Programming_Language/ControlFlow.html#//apple_ref/doc/uid/TP40014097-CH9-ID120

1、Colsures can capture and store references to any constants and variables from the context in which they are difined. This is known as closing over those constants and variables.Swift handles all of the memory management of capturing for you.

colsures能处理和储存来自闭包定义的地方的常量和变量的引用,这就是我们所知道的闭合那些常量和变量。swift能处理所有的内存管理。

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

  • Inferring parameter and return value types from context
  • Implicit returns from single-expression closures
  • Shorthand argument names
  • Trailing closure syntax

2、Global and nested functions ,as introduced in Functions ,are actually special cases of closures.

全局的和嵌套函数都是闭包的特殊形式。

3、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.

闭合表达式是一个未命名用轻量级语法写的闭包,它能能从他们周围的上下文俘获值。

4、Closure Expressions

It is sometimes useful to write shorter versions of function-like constructs without a full declaration and name.

它是有时有用的,写一个更短的函数似得版本,不需要声明和名字

5、Closure expressions are 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.

6、func backward(_ s1: String, _ s2: String) -> Bool {

         return s1 > s2

}

var reversedNames = names.sorted(by: backward)

等价于:

reseredName = names.sorted(by: {(s1: String, s2: String) -> Bool in return s1 > s2})

it can be written on a single line.

7、

(1)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 return 

swif能推断它的参数的类型和返回值的类型。

(2)Because all of types can be inferred,the return arrow (->) and the parentheses around the names of the parameters can also be ommited

因为所有的类型能被推断,环绕参数名字的箭头和括号能被推断。

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

(3)Implicit Return from Single-Expression Closures

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

here ,the function type of the sorted(by :)method’s argument makes it clear that a Bool value must be returned by the closure.Because the closure’s body contains a single expression(s1 > s2)that returns a Bool value, there is no ambiguity, and the return keyword can be omited.

sorted(by:)方法参数的函数类型使得很明白一个bool值通过闭包返回,因为闭包实体包含一个s1 > s2 (这个返回一个bool值),这里没有模糊,return 关键字可以省略

8、Shorthand Argument Names

$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

如果你应用这些参数在闭包的里面,你能忽略闭包的参数从她它的定义

The in keyword can also be ommitted ,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 second String arguments

这里$0 和 $1指向第一个和第二个参数

9、Operator Methods

reversedNames = names.sorted(by: >)

你还可以这样。

这个环节,你还能继续看。

10、trailing closure

(1)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 as a trailing closure instead.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.

如果你传递给一个闭包给一个函数作为函数最后的参数,并且这个闭合表达式是长的,那么代替写成一个trailing closure也是有用的,一个追踪闭包写在函数调用的括号里面,尽管它仍是一个函数的参数,当你应用追踪闭包语法时,你不需要为那个闭包写参数标签作为函数调用的一部分。

  1. someFunctionThatTakesAClosure(closure: {
  2. //
  3. })
  1. someFunctionThatTakesAClosure() {
  2. //
  3. }

(2)The string-sorting  closure from the Closure Expression Syntax section above can be written outside of the sorted(by:) method’s parentheses as a trailing closure.

reversedNames = names.sorted () {   }这就是一个追踪闭包

(3)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 fuction.

如果你有个函数或者方法只有一个参数,这个参数是闭包,你可以给它提供追踪闭包,当你调用函数的时候你不需要在方法和函数的名字后面写括号().

(4 ) after the function or method’s name when you call the fuction.

如果你有个函数或者方法只有一个参数,这个参数是闭包,你可以给它提供追踪闭包,当你调用函数的时候你不需要在方法和函数的名字后面写括号().

(5)Trailing closures are most useful when the closure is sufficiently long that it is not possible to write in inline on a single line.As an example,Swift’s Array type has a map(_:) 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 the item. The nature of the mapping and the type of the returned value is left up to the closure to specify.

追踪闭包常用在当追踪闭包是十分长以致它不可能写在一行线上面,作为一个例子,swift Array 类型有一个map方法,这个方法将闭合表达式作为它的唯一的参数,闭包被在数组里的每个item调用一次,然后返回那个item的映射值(可能是其他类型),映射的性质以及返回值的类型由闭包决定。

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

在给数组里面的每个元素提供闭包之后,map(_:)(映射)方法返回一个包含新的映射值的数组,跟原始数组对应值相同的顺序。

11、Capturing Values

func makeIncrementer(forIncrement amount: Int) -> () -> Int {

      var runnintTotal = 0

      func incremnter() -> Int {

            runningTotal += amount

            return runnintTotol

      }

       return incrementer

}

It does this by capturing a reference to runningTotal and amount from the surrounding function and using them within its own function body.Capturing by reference ensures that runningTotal and amount do not disappear when the call to makeIncrementer ends, and also ensures that runningTotal is available the next time the incrementer function is called.

通过对从函数的周围获取一个runningTotal 和amount的索引,并将他们使用在自己的函数体里,获取了索引确保当对makeIncremnter调用结束后,runningTotal 和 amount 两个变量不会消失,能确保当下次调用incrementer时,runningTotal是可用的。

12、As an optimization ,Swift may instead capture and store a copy if a value is not mutated by a closure , and if the value is not mutated after the closure is created.Swift also handles all memory management involved in disposing of variables when they are no longer needed.

作为swift的一个优化,如果一个值没有被闭包改变,并且闭包创建后,那个值也不该变,那么swift可以代替俘获和存取一个copy值。Swift也处理所有的内存管理包括能处理变量,当这些变量不在使用的时候。

for : incrementByTen()  ——>10

incrementByTen() ———>20

incrementByTen() ———>30

13、If you create a second incrementer ,it will have its own storted reference to a new ,separate runningTotal variable.

如果你创建了第二个incrementer ,它将有自己的索引,指向一个新的分开的runningTotal 变量

let incrementBySeven = makeIncrementer(forIncrement: 7)

incrementBySeven()>>>>>>>>returns a value of 7

14、调用incrementByTen这个函数不会受incrementBySeven影响

incrementByTen()>>>>>>>>returns a value of 40

15、if you assign a closure to 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 uses capture lists to break these strong reference cycles.

如果你给一个类的实例变量赋一个闭包值,那么这个闭包通过指向这个实例或者变量来俘获这个实例,你将在闭包和实例变量之间创造一个强引用。Swift使用capture lists 来打断这些强引用循环。

16、Closures are reference Types

Functions and closures are reference 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 a reference to the function or closure.In the example above, it is the choice of closure that incrementByTen refers to that is constant, and not the contents of the closure itself.

当你将一个函数或者闭包赋值给一个常量或者变量时,事实上,你是设置了一个指向函数或者闭包的常量或者变量,在以上的例子,incremetnByTen 指向的闭包是一个常量而不是闭包的内容。

17、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.

这意味着如果你将一个闭包赋值给两个不同的常量或者变量,这些常量或者变量将指向相同的闭包。

18、A closure is said to escape a 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 @escaping before the parameter’s type to indicate that the closure is allowed to escape.

一个闭包被称作escape function ,是因为这个闭包被作为一个参数给这个函数,但是在函数返回后才被调用,当你声明一个把闭包作为参数之一的函数时,你能先关键字@escaping 在参数前,显示闭包能被允许escape.

19、var completionHandlers: [() -> Void] = []//定义一个装函数的空数组。

func someFuntionWithEscpingClosure(comletionHandler: @escaping () -> Void) {

        completionHandlers.append(comletionHandler)

}

//comletionHandler是一个函数类参数名

20、The someFunctionWithEscapingClosure(_:) 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 compile-time error.

如果你没有在这个函数的参数前加一个@escaping,你可能会得到一个编译器错误

21、Marking a closure with @escaping means you have to refer to self explicitly within the closure.For example, in the code below, the closure passed to someFunctionWithEscapingCLosure:(_:) is an escaping closure,which means it needs to refer to self explicitly. In contrast, the closure passed to someFunctionWithNonescapingClosure(_:) is a nonescaping closure, which means it can refer to self implicitly,

在闭包前加一个@escaping 关键字意味着你能很清楚的关联self(..........)但是相反,被传给someFunctionWithNoneescapingClosure是一个非escaping closure,它不能清晰地关联self.

22、Autoclosures

(1)An autoclosure is a closure that is automatically created to wrap an expression that ’s being passed as an argument to a function.

Autoclosures 是一个被创建来拆分传给函数作为参数的表达式的闭包。

key word:wrap ,closure

(2)It doesn’t take any arguments ,and when it’s called ,it returned the value of the expression that’s wrapped inside of it.当it被调的时候不需要采取任何参数,它返回这个表达拆分后里面的值。

(3)This syntactic conveniences lets you omit braces around a function’s parameter by writing a normal expression instead of an explicit closure.

这个方便的句法通过写一个正常的表达式而不是模糊的闭包,这样让你省略环绕函数参数的花括号。

(4)It’s common to call functions that take autoclosures ,but it’s not common to implement that kind of function .

调用这种有自动闭包的函数很普遍,但是执行这类函数却又不普遍。

for exa:

the  assert(condition:message:file:line:) function takes an autoclosure for its condition and message parameters; its condition parameter is evaluated only in debug builds and its message parameter is evaluated only if condition is false.

assset函数的condition和message参数都是自动闭包类参数,但是condition只有在调试建立的时候才被执行, 它的message参数之后在condition是错的条件下才执行。

(5)An autoclosure lets you delay evaluation ,because the code inside isn’t run untill you call the closure.Delaying evaluation is useful for code that has side effects or is computationally expensive,because it lets you control when thant code is evaluated.

一个自动闭包让你延误执行 ,因为在内部的码只有你调用这个闭包的时候才执行.延迟执行对那些有副作用或者计算上可贵的代码是有用的,因为它你控制代码什么时候执行

(6)Even through the first element of the cumstomersInline array 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 expession inside the closure is never evaluated, which means the array element is never removed.Note that type of customerProvider is not String but(0 -> String -a function with no parameters that returns a string.

尽管数组的第一个元素被在闭包里面的代码移除,可是这个数组的元素只有到了这个闭包被调用的时候才被移除,如果这个闭包从来不会被调用,那么在这个闭包内部的表达式从不被执行,也意味着这数组里面的元素从来不被移走,注意这个customerProvider的类型不是一个字符串,而是一个没有参数能返回一个字符串的函数。

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

过度使用闭包会使你的码变得难以理解,上下文和函数名字应该使执行的延迟很清晰。

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

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

       customerProviders.append(customerProvider)

}

collectCustomerProviders(customersInLine.remove(at: 0))

collectCustomerProviders(customersInLine.remove(at: 0))

for customerProvider in customerProviders {

      print(“Now serving \(customerProvider())!”)

}

In the code above ,instead of calling the closure passed to as its customerProvider argument ,the collectCustomerProviders(_:) function appends the closure to the customerProviders array.The array is declared outside the scope of the function,which means the closures in the array can be executed after the functions returns. As a result, the value of the customerProvider argument must be allowed to escape the function’s scope.

在上面的代码中,这个collectCustomerProviders函数不是调用那个闭包,而是将这个闭包附加到数组array里面,数组在函数的外围声明,这意味着在这个数组里面的闭包只有在函数返回后才被执行,因此,customerProvider参数的值必须允许跳出函数外围。

0 0