//闭包

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. apache下virtualhost与location合用配置转发SVN控制访问

    使用apache的文件系统配置 使用virtualhost 实现location 重定向 NameVirtualHost *:80 <VirtualHost *:80> ServerNam ...

  2. POJ 1804 Brainman

    Brainman Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 7787   Accepted: 4247 Descript ...

  3. 各种UserAgent的列表

    User Agent是浏览器用于 HTTP 请求的用户代理头的值.更换User Agent能更好的模拟出不同的系统和浏览器信息. Android Name User Agent Nexus 7 (Ta ...

  4. HIS系统的处方录入控件

    前文<EFW框架Winform前端开发之强大的自定义控件库>中我们介绍了EFW框架中Winform系统中的自定义控件,本章使用自定义控件中的GridBoxCard控件开发了一个HIS系统的 ...

  5. 审核流(2)流程设计-SNF.WorkFlow功能使用说明--SNF快速开发平台3.1

    流程设计 图形化的流程设计,更方便.直观 1.打开“流程设计“程序,如上.点击”新建“如下: 2.红色部分为必填项,审批对象是选择要审批的程序菜单,单据名称是在审核流流转时用于提示的单据名称,还要选择 ...

  6. D3D的绘制

    一.D3D中的绘制 顶点缓存和索引缓存:IDirect3DVertexBuffer9 IDirect3DIndexBuffer 使用这两缓存而不是用数组来存储数据的原因是,缓存可以被放置在显存中,进行 ...

  7. [ML] Naive Bayes for email classification

    20 Newsgroups (Original) Author: Jeffrey H 1. Introduction This is only a test report for naive baye ...

  8. 【转载】Linux动态库搜索路径的技巧

    转自:http://soft.chinabyte.com/os/232/11488732_2.shtml 众所周知,Linux动 态库的默认搜索路径是/lib和/usr/lib.动态库被创建后,一般都 ...

  9. fcitx 无法启动

    困扰了好久的问题,终于解决了. 问题描述: 在fcitx的输入法配置栏里,输入法列表是空的,使用Ctrl+space无法启用任何的输入法, 当然此截图中的是有的,这是问题已经解决后的状态了. 解决方法 ...

  10. MySQL如何查询两个日期之间的记录

    baidu出来的结果多是下面答案:<quote> MySQL中,如何查询两个日期之间的记录,日期所在字段的类型为datetime(0000-00-00 00:00:00) 解决方案: 直接 ...