目录:

  • 基本语法
  • 尾随闭包
  • 值捕获
  • 自动闭包

闭包是自包含的函数代码块,闭包采取如下三种形式之一:

・全局函数是一个有名字但不会捕获任何值的闭包
・嵌套函数是一个有名字并可以捕获其封闭函数域内值的闭包
・闭包表达式是一个利用轻量级语法所写的可以捕获其上下文中变量或常量值的匿名闭包

使用简洁的闭包表达式具有以下优点:

・利用上下文推断参数和返回值类型
・隐式返回单表达式闭包,即单表达式闭包可以省略 return 关键字
・参数名称缩写
・尾随闭包语法

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

基本语法
{ (parameters) -> returnType in
statements
}
(1). 闭包表达式参数可以是in-out参数,但不能设定默认值
(2). 闭包表达式参数可以使用具体名称的可变参数
(3). 可以使用元组作为闭包表达式的参数和返回值
// 内联闭包
reversedNames = names.sorted(by: { (s1: String, s2: String) -> Bool in
return s1 > s2
}) // 简写方式
reversedNames = names.sorted(by: { (s1: String, s2: String) -> Bool in return s1 > s2 } ) // 内联闭包表达式构造的闭包作为参数传递给函数或方法时,总是能够推断出闭包的参数和返回值类型。
// 这意味着闭包作为函数或者方法的参数时,可以不用完整格式构造内联闭包
reversedNames = names.sorted(by: { s1, s2 in return s1 > s2 } ) // 单行表达式闭包可以通过省略 return 关键字来隐式返回单行表达式的结果
reversedNames = names.sorted(by: { s1, s2 in s1 > s2 } ) // Swift自动为内联闭包提供参数名称缩写功能,可以使用 $0,$1,$2等来顺序调用闭包参数
reversedNames = names.sorted(by: { $ > $ } ) // 运算符方法,String的运算符>刚好接收两个String入参返回Bool结果,可以简写成
reversedNames = names.sorted(by: >)
尾随闭包

如果闭包表达式作为函数最后一个参数,可以使用书写在函数括号之外的省略闭包表达式参数标签的尾随闭包来增强函数的可读性。

func someFunctionThatTakesAClosure(closure: () -> Void) {
// 函数体部分
} // 内联闭包进行函数调用
someFunctionThatTakesAClosure(closure: {
// 闭包主体部分
}) // 尾随闭包进行函数调用
someFunctionThatTakesAClosure() {
// 闭包主体部分
} reversedNames = names.sorted() { $ > $ } // 如果闭包表达式作为函数或方法的唯一参数,则使用尾随闭包时,可以省略()
reversedNames = names.sorted { $ > $ }
值捕获

闭包可以在其被定义的上下文中捕获常量或变量。即使定义这些常量和变量的原作用域已经不存在,闭包仍然可以在闭包函数体内引用和修改这些值。

// makeIncrementer执行完后,runningTotal的作用域不存在了,
// 但调用返回的函数时依然能够改变和访问runningTotal的值
func makeIncrementer(forIncrement amount: Int) -> () -> Int {
var runningTotal =
func incrementer() -> Int {
runningTotal += amount
return runningTotal
}
return incrementer
} let incrementByTen = makeIncrementor(forIncrement: ) // 闭包是引用类型,将闭包同时赋值给两个变量或常量,这两个变量或常量指向同一个闭包
let alsoIncrementByTen = incrementByTen
逃逸闭包

当一个闭包作为函数参数传入,但在函数执行返回之后才被执行,称该闭包为逃逸闭包。可以使用 @escaping 在参数前标注闭包为逃逸闭包,用来指明这个闭包是允许“逃逸”出这个函数的。

异步处理操作通常需要传入一个可以逃逸的闭包作为complete callback,这时往往将传入的闭包保存在函数外部定义的变量中。

var completionHandlers: [() -> Void] = []
func someFunctionWithEscapingClosure(completionHandler: @escaping () -> Void) {
completionHandlers.append(completionHandler)
}

将一个闭包标记为 @escaping 意味着你必须在闭包中显式地引用 self。

func someFunctionWithNonescapingClosure(closure: () -> Void) {
closure()
} class SomeClass {
var x =
func doSomething() {
someFunctionWithEscapingClosure { self.x = }
someFunctionWithNonescapingClosure { x = }
}
}
let instance = SomeClass() instance.doSomething() print(instance.x) // 打印出 "200"
completionHandlers.first?() print(instance.x) // 打印出 "100"
自动闭包

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

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

通过将参数标记为 @autoclosure 来接收一个自动闭包。下面serve()以自动闭包做函数参数可以视为接受String类型参数(而非闭包)的函数来调用。

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

如果像让一个自动闭包可以“逃逸”,则应该同时使用 @autoclosure 和 @escaping 属性。

// customersInLine i= ["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.") // 打印 "Collected 2 closures."
for customerProvider in customerProviders {
print("Now serving \(customerProvider())!")
}
// 打印 "Now serving Barry!"
// 打印 "Now serving Daniella!"
声明:该系列内容均来自网络或电子书籍,只做学习总结!

Swift学习笔记(8):闭包的更多相关文章

  1. Swift学习笔记之闭包

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

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

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

  3. swift学习笔记之-闭包

    //闭包 import UIKit /*闭包(Closures): 函数.闭包.类都是引用类型(引用类型的实例赋值给变量或常量时,得到的都是该实例的引用,而值类型的实例变量得到的是独立的值的拷贝) 1 ...

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

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

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

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

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

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

  7. Swift学习笔记一

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

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

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

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

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

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

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

随机推荐

  1. EF Code First 使用(一)

    第一步:创建MVC5项目,添加数据库实体,建立上下文对象. 第二步:创建数据库和添加数据

  2. Fildder 4接口测试工具Post请求方式

  3. SpringBoot(九) ElasticSearch 全文检索

    ElasticSearch ​ ElasticSearch是一个基于Lucene的搜索服务器.它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口.Elasticsearch是用 ...

  4. JS应用实例1:表格各行换色

    效果如下: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF ...

  5. (转)Django学习之 第三章:动态Web页面基础

    上一章我们解释了怎样开始一个Django项目和运行Django服务器 当然了,这个站点实际上什么也没有做------除了显示了"It worked"这条信息以外. 这一章我们介绍怎 ...

  6. SQL Server-聚焦聚集索引对非聚集索引的影响

      前言 在学习SQL 2012基础教程过程中会时不时穿插其他内容来进行讲解,相信看过SQL Server 2012 T-SQL基础教程的童鞋知道前面写的所有内容并非都是摘抄书上内容,如若是这样那将没 ...

  7. poj 2762 Going from u to v or from v to u? 【 强连通 拓扑排序】

    给出n个点,m条边,问是否任意两点u,v,是否满足u能够到达v,或者v能够到达u 自己写的时候以为缩一下点,然后再判断一下能不能拓扑排序就可以了 但是--wa--- 后来看了这篇题解 http://e ...

  8. 修改properties文件后系统运行异常

    今天修改了项目的properties配置文件以后,运行会报异常,即使将内容改回,异常仍然存在.中间还会出现项目报错等问题,现将解决方法整理出来. 1.修改properties的打开方式,将打开方式从p ...

  9. W3c盒子模型+IE盒子模型+box-sizing属性

    1.盒子模型有两种,标准盒模型和IE盒模型,其中W3C标准的盒模型就是在网页的顶部加上 DOCTYPE 声明. (1)W3C标准的盒模型 W3C盒子模型包括4部分:margin,border,padd ...

  10. 四则运算2(最终版)java+jps+sqlServer

    1,设计思想 (1)在java Resources里建立包和类 (2)在类里面写入方法,其中包括生成算式create()和删除算式delete()用来更新数据库中的题目 (3)Show()方法用来随机 ...