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

在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. 设置session的生命周期(php)

    PHP中,Session变量保存在服务器端(默认以文件格式保存),而Session ID以cookie形式保存在客户端. 销毁session的方法有2种 第一种是通过程序 session_destor ...

  2. thinkphp 中js 实现刷新

    <input name="Button5" value="返回" id="Button5" style="width:56p ...

  3. 那些年被我坑过的Python——一夫当关 第十三章(堡垒机初步设计)

      堡垒机架构 堡垒机的主要作用权限控制和用户行为审计,堡垒机就像一个城堡的大门,城堡里的所有建筑就是你不同的业务系统 , 每个想进入城堡的人都必须经过城堡大门并经过大门守卫的授权,每个进入城堡的人必 ...

  4. 在Apache中利用ServerAlias设置虚拟主机接收多个域名和设置域名泛解析

    ServerAlias:服务器别名,在Apache中可以用于设置虚拟主机接收到个域名,也可以用于接收泛解析的域名.具体的设置方法如下: 一.用于设置虚拟主机接收多个域名 一个虚拟主机常常会接收多个域名 ...

  5. Why your Games are Unfinished, and What To Do About It (转)

    So, you've got a new game idea, and it's going to change what everyone knows about the genre! Great! ...

  6. Unity图片处理类,包括压缩、截屏和滤镜

    先上代码: 1 using System.Threading; using UnityEngine; using System.IO; using System.Collections; public ...

  7. core dump

    Core Dump?! 整理:Wilbur Lang 何谓 core? 在使用半导体作为内存的材料前,人类是利用线圈当作内存的材料(发明 者为王安),线圈就叫作 core ,用线圈做的内存就叫作 co ...

  8. java 对象序列化 RMI

    对于一个存在于Java虚拟机中的对象来说,其内部的状态只保持在内存中.JVM停止之后,这些状态就丢失了.在很多情况下,对象的内部状态是需要被持久化下来的.提到持久化,最直接的做法是保存到文件系统或是数 ...

  9. Bug in Code

    Coder-Strike 2014 - Finals (online edition, Div. 1) C:http://codeforces.com/problemset/problem/420/C ...

  10. Unity NGUI根据高度自适应屏幕分辨率

    Unity版本:4.5.1 NGUI版本:3.6.5 本文内容纯粹转载,转载保留参考链接和作者 参考链接:http://blog.csdn.net/asd237241291/article/detai ...