文档地址:

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参数的值必须允许跳出函数外围。

Swift 3.1(7) Closures的更多相关文章

  1. html5使用canvas实现弹幕功能示例

    这篇文章主要介绍了html5使用canvas实现弹幕功能示例的相关资料,需要的朋友可以参考下

  2. 前端实现弹幕效果的方法总结(包含css3和canvas的实现方式)

    这篇文章主要介绍了前端实现弹幕效果的方法总结(包含css3和canvas的实现方式)的相关资料,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  3. H5 canvas实现贪吃蛇小游戏

    本篇文章主要介绍了H5 canvas实现贪吃蛇小游戏,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  4. ios – 仅在异步函数完成执行后运行代码

    所以,例如:如果问题是你不知道要调用什么函数,你可以配置你周围的函数/对象,这样有人可以给你一个函数,然后你在我上面说“调用函数”的地方调用你的函数.例如:

  5. ios – parse.com用于键,预期字符串的无效类型,但是得到了数组

    我尝试将我的数据保存到parse.com.我已经预先在parse.com上创建了一个名为’SomeClass’的类.它有一个名为’mySpecialColumn’的列,其数据类型为String.这是我尝试使用以下代码保存数据的代码:如果我运行这个我得到:错误:密钥mySpecialColumn的无效类型,预期字符串,但得到数组这就是我在parse.com上的核心外观:有谁知道我为什么会收到这个错误?

  6. ios – Swift相当于`[NSDictionary initWithObjects:forKeys:]`

    Swift的原生字典是否与[NSDictionaryinitWithObjects:forKeys:]相当?假设我有两个带键和值的数组,并希望将它们放在字典中.在Objective-C中,我这样做:当然我可以通过两个数组迭代一个计数器,使用vardict:[String:Int]并逐步添加东西.但这似乎不是一个好的解决方案.使用zip和enumerate可能是同时迭代两者的更好方法.然而,这种方法

  7. ios – 如何使用Objective C类中的多个参数调用Swift函数?

    本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请发送邮件至dio@foxmail.com举报,一经查实,本站将立刻删除。

  8. ios – 上下文类型’NSFastEnumeration’不能与数组文字一起使用

    斯威夫特3,你会这样做吗?解决方法正如您所发现的,您不能使用as-casting将数组文字的类型指定为NSFastEnumeration.您需要找到一个符合NSFastEnumeration的正确类,在您的情况下它是NSArray.通常写这样的东西:

  9. ios – 如何从变量访问属性或方法?

    是否可以使用变量作为Swift中方法或属性的名称来访问方法或属性?在PHP中,您可以使用$object->{$variable}.例如编辑:这是我正在使用的实际代码:解决方法你可以做到,但不能使用“纯粹的”Swift.Swift的重点是防止这种危险的动态属性访问.你必须使用Cocoa的Key-ValueCoding功能:非常方便,它完全穿过你要穿过的字符串到属性名称的桥,但要注意:这里是龙.

  10. ios – Swift中的UIView动画不起作用,错误的参数错误

    我正在尝试制作动画并使用下面的代码.我得到“无法使用类型’的参数列表调用’animateWithDuration'(FloatLiteralConvertible,延迟:FloatLiteralConvertible,选项:UIViewAnimationoptions,动画:()–>()–>$T4,完成:(Bool)–>(Bool)–>$T5)’“错误.这意味着我使用了错误的参数.我错了.请

随机推荐

  1. Swift UITextField,UITextView,UISegmentedControl,UISwitch

    下面我们通过一个demo来简单的实现下这些控件的功能.首先,我们拖将这几个控件拖到storyboard,并关联上相应的属性和动作.如图:关联上属性和动作后,看看实现的代码:

  2. swift UISlider,UIStepper

    我们用两个label来显示slider和stepper的值.再用张图片来显示改变stepper值的效果.首先,这三个控件需要全局变量声明如下然后,我们对所有的控件做个简单的布局:最后,当slider的值改变时,我们用一个label来显示值的变化,同样,用另一个label来显示stepper值的变化,并改变图片的大小:实现效果如下:

  3. preferredFontForTextStyle字体设置之更改

    即:

  4. Swift没有异常处理,遇到功能性错误怎么办?

    本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请发送邮件至dio@foxmail.com举报,一经查实,本站将立刻删除。

  5. 字典实战和UIKit初探

    ios中数组和字典的应用Applicationschedule类别子项类别名称优先级数据包contactsentertainment接触UIKit学习用Swift调用CocoaTouchimportUIKitletcolors=[]varbackView=UIView(frame:CGRectMake(0.0,0.0,320.0,CGFloat(colors.count*50)))backView

  6. swift语言IOS8开发战记21 Core Data2

    上一话中我们简单地介绍了一些coredata的基本知识,这一话我们通过编程来实现coredata的使用。还记得我们在coredata中定义的那个Model么,上面这段代码会加载这个Model。定义完方法之后,我们对coredata的准备都已经完成了。最后强调一点,coredata并不是数据库,它只是一个框架,协助我们进行数据库操作,它并不关心我们把数据存到哪里。

  7. swift语言IOS8开发战记22 Core Data3

    上一话我们定义了与coredata有关的变量和方法,做足了准备工作,这一话我们来试试能不能成功。首先打开上一话中生成的Info类,在其中引用头文件的地方添加一个@objc,不然后面会报错,我也不知道为什么。

  8. swift实战小程序1天气预报

    在有一定swift基础的情况下,让我们来做一些小程序练练手,今天来试试做一个简单地天气预报。然后在btnpressed方法中依旧增加loadWeather方法.在loadWeather方法中加上信息的显示语句:运行一下看看效果,如图:虽然显示出来了,但是我们的text是可编辑状态的,在storyboard中勾选Editable,再次运行:大功告成,而且现在每次单击按钮,就会重新请求天气情况,大家也来试试吧。

  9. 【iOS学习01】swift ? and !  的学习

    如果不初始化就会报错。

  10. swift语言IOS8开发战记23 Core Data4

    接着我们需要把我们的Rest类变成一个被coredata管理的类,点开Rest类,作如下修改:关键字@NSManaged的作用是与实体中对应的属性通信,BinaryData对应的类型是NSData,CoreData没有布尔属性,只能用0和1来区分。进行如下操作,输入类名:建立好之后因为我们之前写的代码有些地方并不适用于coredata,所以编译器会报错,现在来一一解决。

返回
顶部