Swift闭包概念与常见使用场景总结
·Swift 闭包
闭包(Closures)是自包含的功能代码块,可以在代码中使用或者用来作为参数传值。
Swift 中的闭包与 C 和 Objective-C 中的代码块(blocks)以及其他一些编程语言中的 匿名函数比较相似。
全局函数和嵌套函数其实就是特殊的闭包。
闭包的形式有:
全局函数 |
嵌套函数 |
闭包表达式 |
有名字但不能捕获任何值。 |
有名字,也能捕获封闭函数内的值。 |
无名闭包,使用轻量级语法,可以根据上下文环境捕获值。 |
Swift中的闭包有很多优化的地方:
- 根据上下文推断参数和返回值类型
- 从单行表达式闭包中隐式返回(也就是闭包体只有一行代码,可以省略return)
- 可以使用简化参数名,如$0, $1(从0开始,表示第i个参数...)
- 提供了尾随闭包语法(Trailing closure syntax)
闭包表达式
闭包表达式是一种利用简洁语法构建内联闭包的方式。
闭包表达式提供了一些语法优化,使得撰写闭包变得简单明了。
sort 函数
Swift 标准库提供了名为sort的函数,会根据您提供的用于排序的闭包函数将已知类型数组中的值进行排序。
排序完成后,sort(_:)方法会返回一个与原数组大小相同,包含同类型元素且元素已正确排序的新数组,原数组不会被sort(_:)方法修改。
sort(_:)方法需要传入两个参数:
- 已知类型的数组
2. 闭包函数,该闭包函数需要传入与数组元素类型相同的两个值,并返回一个布尔类型值来表明当排序结束后传入的第一个参数排在第二个参数前面还是后面。如果第一个参数值出现在第二个参数值前面,排序闭包函数需要返回true,反之返回false。
参数名称缩写
Swift 自动为内联函数提供了参数名称缩写功能,您可以直接通过$0,$1,$2来顺序调用闭包的参数。
import Cocoa
let names = ["AT", "AE", "D", "S", "BE"]
var reversed = names.sort( { $0 > $1 } )
print(reversed)
$0和$1表示闭包中第一个和第二个String类型的参数。
以上程序执行输出结果为:
["S", "D", "BE", "AT", "AE"]
运算符函数
实际上还有一种更简短的方式来撰写上面例子中的闭包表达式。
Swift 的String类型定义了关于大于号 (>) 的字符串实现,其作为一个函数接受两个String类型的参数并返回Bool类型的值。 而这正好与sort(_:)方法的第二个参数需要的函数类型相符合。 因此,您可以简单地传递一个大于号,Swift可以自动推断出您想使用大于号的字符串函数实现:
import Cocoa
let names = ["AT", "AE", "D", "S", "BE"]
var reversed = names.sort(>)
print(reversed)
以上程序执行输出结果为:
["S", "D", "BE", "AT", "AE"]
尾随闭包
尾随闭包是一个书写在函数括号之后的闭包表达式,函数支持将其作为最后一个参数调用。
注意:如果函数只需要闭包表达式一个参数,当您使用尾随闭包时,您甚至可以把()省略掉。
func someFunctionThatTakesAClosure(closure: () -> Void) {
// 函数体部分
}
// 以下是不使用尾随闭包进行函数调用
someFunctionThatTakesAClosure({
// 闭包主体部分
})
// 以下是使用尾随闭包进行函数调用
someFunctionThatTakesAClosure() {
// 闭包主体部分
}
捕获值
闭包可以在其定义的上下文中捕获常量或变量。
即使定义这些常量和变量的原域已经不存在,闭包仍然可以在闭包函数体内引用和修改这些值。
Swift最简单的闭包形式是嵌套函数,也就是定义在其他函数的函数体内的函数。
嵌套函数可以捕获其外部函数所有的参数以及定义的常量和变量。
闭包是引用类型。
总结:闭包的常见使用场景
目前基于Swift 3.0+ 版本总结闭包的常见使用场景
// 1.作为变量(类中的属性):
// var 闭包名称: (参数列表) -> 返回类型
var closureName1: (_ name: String, _ age: Int) -> String
// 2.作为可选的变量(类中的属性):
// var closureName: ((parameterTypes) -> returnType)?
var closureName2: ((_ name: String, _ age: Int) -> String)?
// 3.作为类型别名(闭包类型):
// typealias closureType = (parameterTypes) -> returnType
typealias closureType = (_ name: String, _ age: Int) -> String
// 4.作为常量(类中的属性):
// let closureName: closureType = 闭包表达式
let closureName3: closureType = { (_ name: String, _ age: Int) -> String in
return "My name is \(name), age is \(age)"
}
closureName3("Abnerzj", 10)
// 5.定义函数时作为函数的参数:
// 5.1 func 函数名(参数名: 闭包类型)
func closureFuncName(closureParameterName: closureType) -> Void {
// 函数体部分
}
// 5.2 func 函数名(参数名: 闭包表达式)
func closureFuncName2(closureParameterName: (_ name: String, _ age: Int) -> String) -> Void {
// 函数体部分
}
// 6.调用函数时作为函数的参数:完整的闭包格式
// 函数名(参数名: 闭包表达式)
// 函数名(参数名: { 闭包参数列表 -> 闭包返回值 in 闭包函数体 })
closureFuncName(closureParameterName: {
(_ name: String, _ age: Int) -> String in
return "My name is" + name + ", age is \(age)"
})
// 7.调用函数时作为函数的参数:根据上下文推断类型:
// 函数名(参数名: { 实参名1, 实参名2 in 闭包函数体 })
closureFuncName(closureParameterName: {
name, age in
return "My name is" + name + ", age is \(age)"
})
// 8.调用函数时作为函数的参数:单行表达式闭包隐式返回,可以隐藏return关键字
// 函数名(参数名: { 实参名1, 实参名2 in 闭包函数体 })
closureFuncName(closureParameterName: {
name, age in "My name is" + name + ", age is \(age)"
})
// 9.调用函数时作为函数的参数:参数名称缩写($0,$1,$2...来顺序代替参数列表中的参数名)
// 函数名(参数名: { 闭包函数体 })
closureFuncName(closureParameterName: {
"My name is \($0), age is \($1)"
})
// 10.调用函数时作为函数的参数:尾随闭包(作为函数的最后一个参数),不是函数的唯一一个参数时
// 函数名() { 闭包函数体 }
closureFuncName() {
"My name is \($0), age is \($1)"
}
// 11.调用函数时作为函数的参数:尾随闭包(作为函数的最后一个参数),是函数的唯一一个参数时
// 函数名 { 闭包函数体 }
closureFuncName {
"My name is \($0), age is \($1)"
}
// 12.调用函数时传入一个闭包函数作为函数的参数
// 函数名(参数名: 闭包函数名)
func closureFunc(_ name: String, _ age: Int) -> String {
return name + "\(age)"
}
closureFuncName(closureParameterName: closureFunc)
// 13.调用函数时作为函数的参数:循环强引用
// 函数名(参数名: { [弱引用或无主引用列表] 闭包参数列表 -> 闭包返回值 in 闭包函数体 })
// 第一种:推荐
closureFuncName(closureParameterName: {
[weak self] (_ name: String, _ age: Int) -> String in
self?.view.backgroundColor = UIColor.red
return "My name is" + name + ", age is \(age)"
})
// 第二种:
weak var weakself = self
closureFuncName(closureParameterName: {
(_ name: String, _ age: Int) -> String in
weakself?.view.backgroundColor = UIColor.red
return "My name is" + name + ", age is \(age)"
})
// 第三种:
closureFuncName(closureParameterName: {
[unower self] (_ name: String, _ age: Int) -> String in
self?.view.backgroundColor = UIColor.red
return "My name is" + name + ", age is \(age)"
})
上面是我对Swift闭包的理解与总结。欢迎各位博友学习浏览,如在哪里总结的不到位希望各位朋友提出更好的建议。
此博文只是为了与更多博友们交流学习心得,如需转载请注明出处。 谢谢!
关于闭包的总结就到此处啦! 觉得此博文整理的好的话,就给个赞吧。。。 感谢大家的支持!!!
转载于:https://www.cnblogs.com/ZRJ-boke/p/6104620.html
Swift闭包概念与常见使用场景总结相关推荐
- JS闭包的理解及常见应用场景
JS闭包的理解及常见应用场景 一.总结 一句话总结: 闭包是指有权访问另一个函数作用域中的变量的函数 1.如何从外部读取函数内部的变量,为什么? 闭包:f2可以读取f1中的变量,只要把f2作为返回值, ...
- 面试官:谈谈对JS闭包的理解及常见应用场景(闭包的作用)
文章目录 对JS闭包的理解及常见应用场景(闭包的作用) 1.变量作用域 2.如何从外部读取函数内部的变量? 3.闭包概念 4.闭包用途 5.闭包的理解 6.闭包应用场景 setTimeout传参 回调 ...
- 计算机显微视觉相关概念,机器视觉的概念及常见应用
原标题:机器视觉的概念及常见应用 机器视觉的概念及常见应用 机器视觉的相关概念 下面我们将开始进行机器视觉的学习,那么什么实机器视觉呢?可能还有同学听说过计算机视觉, 还有当前比较火的机器学习,人工智 ...
- 由SoC到SOPC、SoC FPGA ,异同优缺点的介绍及常见应用场景
由SoC到SOPC.SoC FPGA ,异同优缺点的介绍及常见应用场景 目录 由SoC到SOPC.SoC FPGA ,异同优缺点的介绍及常见应用场景 说一说 一.关于SoC 二.关于SOPC 1.概念 ...
- 大数据常见应用场景及架构改进
大数据常见应用场景及架构改进 大数据典型的离线处理场景 1.大数据数据仓库及它的架构改进 2.海量数据规模下的搜索与检索 3.新兴的图计算领域 4.海量数据挖掘潜在价值 大数据实时处理场景 大数据典型 ...
- 从λ演算到函数式编程聊闭包(1):闭包概念在Java/PHP/JS中形式
什么是闭包 如果让谷哥找一下"闭包"这个词,会发现网上关于闭包的文章已经不计其数 维基百科上对闭包的解释就很经典: 在计算机科学中,闭包(Closure)是词法闭包(Lexical ...
- 原来 JS 也支持跟 Lua 语意一样的内嵌函数的闭包概念
原来 JS 也支持跟 Lua 语意一样的内嵌函数的闭包概念. 我是从这里看来的: http://blog.dreambrook.com/soloist/archive/2005/03/13/526.a ...
- 分库分表学习总结(4)——分布式事务常见应用场景总结
前言 设计一个分布式事务框架前,首先要明确问题到定义.分析具体应用场景,包括以下三个:A.服务内跨数据库的事务:B.跨内部服务的事务:C.跨外部服务的事务.其中划分内部和外部的标准是:内部服务我们可以 ...
- Lambda表达式的生动理解以及Java Lambda表达式常见使用场景
本篇承接上一篇 Java Lambda 表达式快速学习 , 对Lambda 表达式的语法格式进行演化说明, 并对Java 中Lambda表达式的常见使用场景进行说明. Lambda 表达式怎么来的? ...
- Lucene 概念,定义应用场景
Lucene 概念,定义应用场景 转载于:https://www.cnblogs.com/TendToBigData/p/10501324.html
最新文章
- 测序数据的处理方法及装置制造方法及图纸
- 网络嗅探软件全接触(1)
- Python中的多进程创建和传值(克隆)Queue方法
- Carlosfu技术系列文章总目录
- “看看人家苹果和亚马逊”,嫌薪酬太低,谷歌员工“炮轰”高管
- hiho 第118周 网络流四·最小路径覆盖
- atitit.为什么技术的选择方法java超过.net有前途
- DirectX SDK (June 2010)安装遇到Error Code S1023
- 使用LaTeX给PDF加背景
- windows下安装,配置gcc编译器
- 一淘网发声明否认胁迫导航网站合作
- 如何下载微信公众号视频
- 蓝桥杯 单片机 决赛 第7届 电压、频率采集设备
- centos浏览器可以上外网但是ping不通
- ZPL 打印条码、二维码及小票(中文/汉字),生成条码、二维码图片【Asp.Net】-含示例代码
- 关于Matplotlib实验中出现NameError: name ‘rgb2gray‘ is not defined的解决
- 这可能是JAVA程序员进阶架构师的最佳之路了 !
- Windows10数字权利
- 英语六级选词填空技巧
- IDEA无法识别项目中的Java类