//闭包

import UIKit

/*闭包(Closures):

函数、闭包、类都是引用类型(引用类型的实例赋值给变量或常量时,得到的都是该实例的引用,而值类型的实例变量得到的是独立的值的拷贝)

1.闭包是自包含的函数代码块,可以在代码中被传递和使用,与匿名函数比较相似,嵌套函数也是一种闭包

2.闭包可以捕获和存储其所在上下文中任意常量和变量的引用。这就是所谓的闭合并包裹着这些常量和变量,俗称闭包

在函数章节中介绍的全局和嵌套函数实际上也是特殊的闭包,闭包采取如下三种形式之一:

1.全局函数是一个有名字但不会捕获任何值的闭包

2.嵌套函数是一个有名字并可以捕获其封闭函数域内值的闭包

3.闭包表达式是一个利用轻量级语法所写的可以捕获其上下文中变量或常量值的匿名闭包

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

1.利用上下文可推断参数和返回值类型,则可省略其类型定义

2.隐式返回单表达式闭包,即单表达式闭包可以省略return关键字

3.若参数类型可推断,则参数名称可缩写,省略对参数的定义,直接通过$0,$1,$2...来顺序调用闭包的参数,in关键字也同样可以被省略

4.尾随(Trailing)闭包语法

闭包表达式语法有如下一般形式:{类型 in 主体}

{ (parameters) -> returnType in

statements

}

闭包表达式语法:可以使用常量、变量和inout类型作为参数,不能提供默认值。也可以在参数列表的最后使用可变参数。元组也可以作为参数和返回值。

尾随闭包(Trailing Closures):如果您需要将一个很长的闭包表达式作为最后一个参数传递给函数,可以使用尾随闭包来增强函数的可读性

非逃逸闭包(Nonescaping Closures)

1.当一个闭包作为参数传到一个函数中,但是这个闭包在函数返回之后才被执行,我们称该闭包从函数中逃逸

2.当你定义接受闭包作为参数的函数时,你可以在参数名之前标注@noescape,用来指明这个闭包是不允许“逃逸”出这个函数的

3.将闭包保存在一个在函数外部定义的变量中,再通过这个变量来做为函数的参数,这样能使闭包“逃逸”出函数,这个闭包可以在函数返回之后被调用

自动闭包(Autoclosures)

1.自动闭包是一种自动创建的闭包,用于包装传递给函数作为参数的表达式。这种闭包不接受任何参数,当它被调用的时候,会返回被包装在其中的表达式的值。这种便利语法让你能够用一个普通的表达式来代替显式的闭包,从而省略闭包的花括号。

2.自动闭包让你能够延迟求值,因为代码段不会被执行直到你调用这个闭包。延迟求值对于那些有副作用(Side Effect)和代价昂贵的代码来说是很有益处的,因为你能控制代码什么时候执行。

3.通过将参数标记为@autoclosure将参数转化为一个自动闭包,@autoclosure特性暗含了@noescape特性,这个特性在非逃逸闭包一节中有描述。如果你想让这个闭包可以“逃逸”,则应该使用@autoclosure(escaping)特性.

*/

//=======sort()方法==========

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

func backwards(s1: String, s2: String) -> Bool {

return s1 > s2

}

var reversed = names.sort(backwards)

// reversed 为 ["Ewa", "Daniella", "Chris", "Barry", "Alex"]

//====以下是闭包表达式写法,功能一样

reversed = names.sort( { (s1: String, s2: String) -> Bool in return s1 > s2 } )

//根据上下文推断参数类型为(String,String)->Bool,所以可以省略

reversed = names.sort( { s1, s2 in return s1 > s2 } )

//单行表达式闭包可以通过省略return关键字来隐式返回单行表达式的结果

reversed = names.sort( { s1, s2 in s1 > s2 } )

//Swift 自动为内联闭包提供了参数名称缩写功能,您可以直接通过$0,$1,$2来顺序调用闭包的参数,以此类推.如果您在闭包表达式中使用参数名称缩写,您可以在闭包参数列表中省略对其的定义,并且对应参数名称缩写的类型会通过函数类型进行推断。in关键字也同样可以被省略

reversed = names.sort( { $0 > $1 } )

//如果参数类型和返回值类型正好与函数所需要的相符合,如sort函数,可以简单地传递一个大于号,Swift 可以自动推断出您想使用大于号的字符串函数实现:

reversed = names.sort(>)

//使用尾随闭包

reversed = names.sort() { $0 > $1 }  //可以省略()

reversed = names.sort { $0 > $1 }

//=========Array类型中的map()映射方法========

let digitNames = [

0: "Zero", 1: "One", 2: "Two",   3: "Three", 4: "Four",

5: "Five", 6: "Six", 7: "Seven", 8: "Eight", 9: "Nine"

]

let numbers = [16, 58, 510]

let strings = numbers.map {     //因为闭包比较长,所以使用尾随闭包,省略了map方法的()

(var number) -> String in   //将整个闭包作为map()的参数,output传入map方法中

var output = ""

while number > 0 {

output = digitNames[number % 10]! + output

number /= 10

}

return output

}

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

// 其值为 ["OneSix", "FiveEight", "FiveOneZero"]

//=============自动闭包,延时求值==================

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

print(customersInLine.count)

// prints "5"

let customerProvider = { customersInLine.removeAtIndex(0) }

print(customersInLine.count)

// prints "5"

print("Now serving \(customerProvider())!")     //此处调用才计算闭包的值,customerProvider是一个函数,所以调用他要加()

// prints "Now serving Chris!"

print(customersInLine.count)

// prints "4"

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

//======将闭包作为参数传递给函数时,你能获得同样的延时求值行为

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

func serveCustomer(customerProvider:()->String) {

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

}

serveCustomer( { customersInLine.removeAtIndex(0) } )

// prints "Now serving Alex!"

//=========@autoclosure转化为自动闭包=====

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

func serveCustomer(@autoclosure customerProvider: () -> String) {

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

}

serveCustomer(customersInLine.removeAtIndex(0))

// prints "Now serving Ewa!"

//=========@autoclosure(escaping)可逃逸的自动闭包====

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

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

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

customerProviders.append(customerProvider)

}

collectCustomerProviders(customersInLine.removeAtIndex(0))

collectCustomerProviders(customersInLine.removeAtIndex(0))

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学习笔记之闭包

    简介 (真的很简) 闭包的完整形态是这个样子的: { (parameters) -> returnType in statements } 写在一行里就是这样: {(parameters) -& ...

  2. Swift学习笔记(9)--闭包

    1.闭包表达式: { (parameters) -> returnType in statements } 注1.闭包表达式语法可以使用常量.变量和inout类型作为参数,不提供默认值. 也可以 ...

  3. 【swift学习笔记】二.页面转跳数据回传

    上一篇我们介绍了页面转跳:[swift学习笔记]一.页面转跳的条件判断和传值 这一篇说一下如何把数据回传回父页面,如下图所示,这个例子很简单,只是把传过去的数据加上了"回传"两个字 ...

  4. Swift学习笔记(一)搭配环境以及代码运行成功

    原文:Swift学习笔记(一)搭配环境以及代码运行成功 1.Swift是啥? 百度去!度娘告诉你它是苹果最新推出的编程语言,比c,c++,objc要高效简单.能够开发ios,mac相关的app哦!是苹 ...

  5. swift学习笔记2——函数、闭包

    之前学习swift时的个人笔记,根据github:the-swift-programming-language-in-chinese学习.总结,将重要的内容提取,加以理解后整理为学习笔记,方便以后查询 ...

  6. Swift学习笔记一

    最近计划把Swift语言系统学习一下,然后将MagViewer用这种新语言重构一次,并且优化一下,这里记录一下Swift的学习笔记. Swift和Objective-C相比,在语法和书写形式上做了很多 ...

  7. 记录:swift学习笔记1-2

    swift还在不断的更新做细微的调整,都说早起的鸟儿有虫吃,那么我们早点出发吧,趁着国内绝大多数的coder们还没有开始大范围普遍应用. 网上有些大神说:swift很简单!我不同意这个观点,假如你用h ...

  8. swift学习笔记5——其它部分(自动引用计数、错误处理、泛型...)

    之前学习swift时的个人笔记,根据github:the-swift-programming-language-in-chinese学习.总结,将重要的内容提取,加以理解后整理为学习笔记,方便以后查询 ...

  9. swift学习笔记4——扩展、协议

    之前学习swift时的个人笔记,根据github:the-swift-programming-language-in-chinese学习.总结,将重要的内容提取,加以理解后整理为学习笔记,方便以后查询 ...

随机推荐

  1. XCActionBar 「Xcode 中的 Alfred」

    下载地址:https://github.com/pdcgomes/XCActionBar 基本命令: (1)「command+shift+8」或者双击「command」键可以打开「动作输入框窗口」 ( ...

  2. 译:在ASP.NET中如何对cookies进行加密和解密

    译文地址:http://www.codeproject.com/Tips/872826/Encrypt-Decrypt-Cookies-in-ASP-NET 源代码:http://files.cnbl ...

  3. .NET 相关工具

    加密工具,反DUMP,反调试,反编译,加密代码资源内容,混淆流程,变量.Confuser is a protector/obfuscator for .NET, providing great sec ...

  4. 【PRML读书笔记-Chapter1-Introduction】引言

    模式识别领域主要关注的就是如何通过算法让计算机自动去发现数据中的规则,并利用这些规则来做一些有意义的事情,比如说,分类. 以数字识别为例,我们可以根据笔画规则启发式教学去解决,但这样效果并不理想. 我 ...

  5. Lua中的weak表——weak table

    弱表(weak table)是一个很有意思的东西,像C++/Java等语言是没有的.弱表的定义是:A weak table is a table whose elements are weak ref ...

  6. 64位Win7下安装与配置PHP环境【Apache+PHP+MySQL】

    [软件下载] 本安装实例所使用安装文件如图所示: 其中,64位版本的MySQL安装文件mysql-5.5.33-winx64.msi,可直接从官网下载,下载地址:http://dev.mysql.co ...

  7. 没有Google的日子很难过...But you can try...

    作为开发人员,经常会通过Google查询一些资料(别问我为什么不用百度,当你输入关键字,然后给你提示没有查询到结果,或者一页全是垃圾资料的时候你就知道了).但是,N个月前,Google不好使了,同时N ...

  8. 使用Html5+C#+微信 开发移动端游戏详细教程:(六)游戏界面布局与性能优化

    本篇教程我们主要讲解在游戏界面上的布局一般遵循哪些原则和一些性能优化的通用方法. 接着教程(五),我们通过Loading类一次性加载了全部图像素材,现在要把我们所用到的素材变成图片对象显示在界面上,由 ...

  9. web.config中httpRunTime的属性

    配置httpRuntime也可以让FileUpload上传更大的文件,不过设置太大了会因用户将大量文件传递到该服务器而导致的拒绝服务攻击(属性有说明) <httpRuntime> < ...

  10. Linux动态库的搜索路径

    下面是目录结构: pengdl@localhost:~$ tree test/test/├── fun.c├── Fun.h└── t1    └── main.c 1 directory, 3 fi ...