目录:

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

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

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

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

・利用上下文推断参数和返回值类型
・隐式返回单表达式闭包,即单表达式闭包可以省略 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. 18.QT消息链筛选机制以及组合键

    mainwindow.h #ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> 5 #include <Q ...

  2. ChildViewController

    View Controller中可以添加多个sub view,在需要的时候显示出来: 可以通过viewController(parent)中可以添加多个child viewController;来控制 ...

  3. POJ 3764 DFS+trie树

    题意: 给你一棵树,求树中最长的xor路径.(n<=100000) 思路: 首先我们知道 A xor B =(A xor C) xor (B xor C) 我们可以随便选一个点DFS 顺便做出与 ...

  4. jar文件配置冲突问题transformResourcesWithMergeJavaResForDebug

    先看本人AS报错异常 Error:Execution failed for task ':app:transformResourcesWithMergeJavaResForDebug'. > c ...

  5. SQL学习——基础语句(4)

    前面感觉真的好乱,想哪,写哪.这里慢慢整理…… SQL Having 语句 还是前面的那两个表: grade表: student表: 我们需要查找这里的s_id下的gradeValue的和,这就要分组 ...

  6. 用IIS怎样在局域网内建网站

    IIS服务器组建一览 IIS(Internet Information Server,互联网信息服务)是一种Web(网页)服务组件,其中包括Web服务器.FTP服务器.NNTP服务器和SMTP服务器, ...

  7. 第一次接触Arduino

    1.百度百科: Arduino包含两个主要的部分:硬件部分是可以用来做电路连接的Arduino电路板:另外一个则是 Arduino IDE,你的计算机中的程序开发环境.你只要在IDE中编写程序代码,将 ...

  8. 记一次html页面传值给另一个html并解码

    前言 由于最近写项目用到layui中的table.render,好像是直接由当前html直接与后台controller取数据,由一方(后台)遍历列表给html,而如果当前html需要传值给这个后台co ...

  9. Pyhton学习——Day29

    #异常与错误# 什么是异常?# 异常就是程序运行时发生错误的信号,在程序出现错误时,则会产生异常,若没有程序处理,则会抛出异常# 导致程序在异常语句处崩溃终止# Traceback 追踪异常信号:** ...

  10. 9、Collaborative Metric Learning Recommendation System: Application to Theatrical Movie Releases------CML推荐系统(电影院放映的应用)

    一.摘要: 主要是做一个基于协作(深度)度量学习(CML)的系统来预测新剧场版本的购买概率.即测量产品的空间距离来预测购买概率. 二.模型 该图分为两部分,先计算右边,右边通过深度度量学习(DDML) ...