//闭包

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. 现代JavaScript开发者的工具箱

    自从HTML5变得流行以来,整个Web平台取得了长足的进步,人们也开始将JavaScript视为一门能够创建复杂应用的语言.许多新的API纷纷浮现,而关于浏览器如何应用这些技术的文章也大量涌现. 作为 ...

  2. Android NDK中的C++调试踩坑标记

    RT, Android NDK中的C++调试, GDB调试比较麻烦,在ADT Eclipse中: 1.配置好NDK给工程加上Native Support 2.编译中加上NDK_DEBUG=1 3.然后 ...

  3. 墓地雕塑-LA3708

    https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&category=20& ...

  4. SQL查询集合合并成字符串

    有时候需要查询某一个字段,并把查询结果组成一个字符串,则: ) SELECT @str=isnull(@str+',','')+列名 FROM 表名 SELECT @str

  5. 【NS2仿真】TCP协议

    # # ftp # \ # tcp sink # \ / # n0--------5M 2ms---------n1 # # set ns [new Simulator] set f [open ou ...

  6. Qt5 从头学(2)--手动构建HelloWold

    在上一篇随笔中已经搭建好了Qt5的的开发环境,并且通过Qt Creator自动构建了一个视窗程序.在这篇文章中我们将手动编写一个HelloWold程序,简单了解一下Qt的构建过程.这里我们不会涉及到Q ...

  7. linux rdate

    检查服务器时间,发现服务器时间与当前时间错了很多.于是调整. 使用ntpdate ,不管如何设置,包括关闭防火期,设置ntp.conf,结果都不成功. 随即使用网上提供的另外一种方法,临时先解决一下燃 ...

  8. Mina、Netty、Twisted一起学(二):TCP消息边界问题及按行分割消息

    在TCP连接开始到结束连接,之间可能会多次传输数据,也就是服务器和客户端之间可能会在连接过程中互相传输多条消息.理想状况是一方每发送一条消息,另一方就立即接收到一条,也就是一次write对应一次rea ...

  9. datatables.js 简单使用--多选框和服务器端分页

    说明:datatables是一款jQuery表格插件.感觉EasyUI的datagrid更易用 内容:多选框和服务器端分页 缘由:写这篇博客的原因是datatables的文档写的不怎么样,找东西很麻烦 ...

  10. 如何在java中使用sikuli进行自动化测试

    很早之前写过一篇介绍sikuli的文章.本文简单介绍如何在java中使用sikuli进自动化测试. 图形脚本语言sikuli sikuli IDE可以完成常见的单击.右击.移动到.拖动等鼠标操作,ja ...