闭包可以从定义它的上下文中捕获常量和变量。

在Swift中,捕获值最简单的例子是嵌套函数,举个例子:

 func makeIncrementer(forIncrement amount: Int) -> () -> Int {
var runningTotal =
func incrementer() -> Int {
runningTotal += amount
return runningTotal
}
return incrementer
}

在这个例子中incrementer()捕获两个值,分别是amount、runningTotal。可以运行一下,观察结果:

 let incrementByTen = makeIncrementer(forIncrement: )
print(incrementByTen()) //
print(incrementByTen()) //20
let incrementByNine = makeIncrementer(forIncrement: )
print(incrementByNine()) //
print(incrementByNine()) //18
print(incrementByTen()) //

注意:如果你把闭包赋值给一个类实例的一个属性,并且闭包通过指向(refer fo)实例或者实例的成员捕获值,那么,在闭包和这个实例间就会有一个强引用环。

闭包是引用类型(Reference Types)

闭包和函数都是引用类型。

Nonescaping Closures

当一个闭包作为参数传递给一个函数,但是在函数返回后调用的时候,我们说一个闭包是escaped的。当你声明一个有一个闭包作为参数的函数的时候,你可以在参数类型前写@nonescape来暗示这个closure不允许escape。如:

 func someFunctionWithNonescapingClosure(closure: @noescape () -> Void) {
closure()
}

把一个闭包标记用@nonescape让你在闭包内隐式的引用(refer to)self,看下这个例子:

 class SomeClass {
var x =
func doSomething() {
someFunctionWithNonescapingClosure { x = }
someFunctionWithEscapingClosure { self.x = }
}
} let instance = SomeClass()
instance.doSomething()
print(instance.x)
// Prints "200" completionHandlers.first?()
print(instance.x)
// Prints "100"

Autoclosures

An autoclosure is 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.

Autoclosures可以延迟计算(delay evaluation),因为直到调用闭包时,闭包内的代码才被运行。延迟计算对于有副作用或者计算代价昂贵的代码非常有用,因为你可以控制什么时候代码进行evaluation。

 var customersInLine = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
print(customersInLine.count)
// Prints "5" let customerProvider = { customersInLine.remove(at: ) }
print(customersInLine.count)
// Prints "5" print("Now serving \(customerProvider())!")
// Prints "Now serving Chris!"
print(customersInLine.count)
// Prints "4"

也可以传递给一个参数:

 // customersInLine is ["Alex", "Ewa", "Barry", "Daniella"]
func serve(customer customerProvider: () -> String) {
print("Now serving \(customerProvider())!")
}
serve(customer: { customersInLine.remove(at: ) } )
// Prints "Now serving Alex!"

使用@autoclosure:

 // customersInLine is ["Ewa", "Barry", "Daniella"]
func serve(customer customerProvider: @autoclosure () -> String) {
print("Now serving \(customerProvider())!")
}
serve(customer: customersInLine.remove(at: ))
// Prints "Now serving Ewa!"

注意:滥用autoclosure会使代码晦涩难懂。

@autoclosure属性隐含了@nonescape属性,如果你想要一个autoclosure允许esacpe,可以这样使用 @autoclosure(escaping) ,如:

 // customersInLine is ["Barry", "Daniella"]
var customerProviders: [() -> String] = []
func collectCustomerProviders(_ customerProvider: @autoclosure(escaping) () -> String) {
customerProviders.append(customerProvider)
}
collectCustomerProviders(customersInLine.remove(at: ))
collectCustomerProviders(customersInLine.remove(at: )) print("Collected \(customerProviders.count) closures.")
// Prints "Collected 2 closures."
for customerProvider in customerProviders {
print("Now serving \(customerProvider())!")
}
// Prints "Now serving Barry!"
// Prints "Now serving Daniella!"

Swift的闭包(二):捕获值的更多相关文章

  1. Swift中文教程(二)--简单值

    原文:Swift中文教程(二)--简单值 Swift使用let关键字声明常量,var关键字声明变量.常量无需在编译时指定,但至少要被赋值一次.也就是说,赋值一次多次使用: var myVariable ...

  2. swift 学习(二)基础知识 (函数,闭包,ARC,柯里化,反射)

    函数 func x(a:Int, b:Int)  {}   func x(a:Int, b:Int) -> Void {}  func x(a:Int, b:Int) ->(Int,Int ...

  3. Swift:闭包

    一.闭包的介绍 闭包表达式(Closure Expressions) 尾随闭包(Trailing Closures) 值捕获(Capturing Values) 闭包是引用类型(Closures Ar ...

  4. Swift:闭包(Closures)

    一. 基本概念 闭包(Closures)是自包括的功能代码块,能够在代码中使用或者用来作为參数传值. 在Swift中的闭包与C.OC中的blocks和其他编程语言(如C#)中的lambda, java ...

  5. Swift: 比较Swift中闭包传值、OC中的Block传值

    一.介绍 开发者对匿名函数应该很清楚,其实它就是一个没有名字的函数或者方法,给人直观的感觉就是只能看到参数和返回值.在iOS开发中中,它又有自己的称呼,在OC中叫Block代码块,在Swift中叫闭包 ...

  6. Swift学习--闭包的简单使用(三)

    一.Swift中闭包的简单使用 override func viewDidLoad() { super.viewDidLoad() /** 闭包和OC中的Block非常相似 OC中的block类似于匿 ...

  7. iOS - Swift Closure 闭包

    1.Closure 闭包在 Swift 中非常有用.通俗的解释就是一个 Int 类型里存储着一个整数,一个 String 类型包含着一串字符,同样,闭包是一个包含着函数的类型.有了闭包,你就可以处理很 ...

  8. swift学习(二)--基本运算符、字符串、集合操作

    在这一篇博客里面,我想要介绍一下swift里面一些常用的基本运算符,还有涉及到的字符串,集合操作.你会发现在swift里面还是有许多其他语言所不具有的特性运算操作的. 首先最基本的+,-,*,/,&g ...

  9. Swift的闭包(一):闭包简介、闭包表达式的优化

    定义:Closures are self-contained blocks of functionality that can be passed around and used in your co ...

随机推荐

  1. 简单概述 .NET Framework 各版本区别

    目前已发行的版本有1.0.1.1.2.0.3.0.3.5.4.0.4.5(及4.5.1.4.5.2).4.6(及4.6.1). 1.0版本:最初的.net framework版本,作为一个独立的工具包 ...

  2. ng的数据绑定

    ng创建了一个自己的事件循环,当浏览器事件(常用的dom事件,xhr事件等)发生时,对DOM对应的数据进行检查,若更改了,则标记为脏值,并进入更新循环,修改对应的(可能是多个) DOM的参数.这样就实 ...

  3. atoi的实现

    #include <iostream> using namespace std; int atoi(char* s) { int retval=0; int n=1; if (*s=='- ...

  4. IIC 概述之1

    概述: I²C 是Inter-Integrated Circuit的缩写,发音为"eye-squared cee" or "eye-two-cee" , 它是一 ...

  5. Github Https方式push错误”Empty reply from server”

                  1 2 3 4 5 6 7 8 9 10 2014-11-19 20:41:30.130 GitHub for Mac Login[2595:326257] AskPass ...

  6. tableview 编辑状态设置

    #pragma mark - tableview 编辑状态设置 -(BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSI ...

  7. js两个时间相减

    平常总会遇到需要算两个日期之间是多少天,以下是使用JavaScript算时间差多少天的: // 给日期类对象添加日期差方法,返回日期与diff参数日期的时间差,单位为天 Date.prototype. ...

  8. 字符串处理---统计每一行字符串当中的字符“u”个数

    package com.guoxiaoming.string; import java.io.BufferedReader; import java.io.FileInputStream; impor ...

  9. 转:11个实用但你可能不知道的Python程序库

    原文来自于:http://www.techug.com/11-python-libraries-you-might-not-know 目前,网上已有成千上万个Python包,但几乎没有人能够全部知道它 ...

  10. 转:PHP之Traits

    原文来自于:http://www.cnblogs.com/tekkaman/archive/2012/12/12/2814214.html 1.Traits基础 2.优先级:当前类中的方法会覆盖 Tr ...