Swift3.0 闭包整理
语法表达式
一般形式:{
(parameters) -> returnType in
statements
}
这里的参数(parameters),可以是in-out(输入输出参数),但不能设定默认值。如果是可变参数,必须放在最后一位,不然编译器报错。元组也可以作为参数或者返回值。
"in"关键字表示闭包的参数和返回值类型定义已经完成,闭包函数体即将开始。即由in引入函数
例子
//一般形式
let calAdd:(Int,Int)->(Int) = {
(a:Int,b:Int) -> Int in
return a + b
}
print(calAdd(100,150)) //Swift可以根据闭包上下文推断参数和返回值的类型,所以上面的例子可以简化如下
let calAdd2:(Int,Int)->(Int) = {
a,b in //也可以写成(a,b) in
return a + b
}
print(calAdd2(150,100))
//上面省略了返回箭头和参数及返回值类型,以及参数周围的括号。当然你也可以加括号,为了好看点,看的清楚点。(a,b) //单行表达式闭包可以隐式返回,如下,省略return
let calAdd3:(Int,Int)->(Int) = {(a,b) in a + b}
print(calAdd3(50,200)) //如果闭包没有参数,可以直接省略“in”
let calAdd4:()->Int = {return 100 + 150}
print("....\(calAdd4())") //这个写法,我随便写的。打印出“我是250”
//这个是既没有参数也没返回值,所以把return和in都省略了
let calAdd5:()->Void = {print("我是250")}
calAdd5()
归纳
闭包类型是由参数类型和返回值类型决定,和函数是一样的。比如上面前三种写法的闭包的闭包类型就是(Int,Int)->(Int)
,后面的类型分别是()->Int
和()->Void
。分析下上面的代码:let calAdd:(add类型)
。这里的add类型就是闭包类型(Int,Int)->(Int)
。意思就是声明一个calAdd常量,其类型是个闭包类型。"="右边是一个代码块,即闭包的具体实现,相当于给左边的add常量赋值。兄弟们,是不是感觉很熟悉了,有点像OC中的block代码块。
起别名
也可以关键字“typealias”先声明一个闭包数据类型。类似于OC中的typedef起别名
typealias AddBlock = (Int, Int) -> (Int) let Add:AddBlock = {
(c,d) in
return c + d
} let Result = Add(100,150)
print("Result = \(Result)")
尾随闭包
若将闭包作为函数最后一个参数,可以省略参数标签,然后将闭包表达式写在函数调用括号后面
func testFunction(testBlock: ()->Void){
//这里需要传进来的闭包类型是无参数和无返回值的
testBlock()
}
//正常写法
testFunction(testBlock: {
print("正常写法")
})
//尾随闭包写法
testFunction(){
print("尾随闭包写法")
}
//也可以把括号去掉,也是尾随闭包写法。推荐写法
testFunction {
print("去掉括号的尾随闭包写法")
}
值捕获
闭包可以在其被定义的上下文中捕获常量或变量。Swift中,可以捕获值的闭包的最简单形式是嵌套函数,也就是定义在其他函数的函数体内的函数。
func captureValue(sums amount:Int) -> ()->Int{
var total = 0
func incrementer()->Int{
total += amount
return total
}
return incrementer
} print(captureValue(sums: 10)())
print(captureValue(sums: 10)())
print(captureValue(sums: 10)())
//打印"10 10 10"
这里没有值捕获的原因是,没有去用一个常量或变量去引用函数,所以每次使用的函数都是新的。有点类似于OC中的匿名对象。
let referenceFunc = captureValue(sums: 10)
print(referenceFunc())
print(referenceFunc())
print(referenceFunc())
//打印"10 20 30"
这里值捕获了,是因为函数被引用了,所以没有立即释放掉。所以函数体内的值可以被捕获
闭包形式
func captureValue2(sums amount:Int) -> ()->Int{
var total = 0
let AddBlock:()->Int = {
total += amount
return total
}
return AddBlock
} let testBlock = captureValue2(sums: 100)
print(testBlock())
print(testBlock())
print(testBlock())
由上面的例子都可以证得,函数和闭包都是引用类型。
逃逸闭包
当一个闭包作为参数传到一个函数中,需要这个闭包在函数返回之后才被执行,我们就称该闭包从函数种逃逸。一般如果闭包在函数体内涉及到异步操作,但函数却是很快就会执行完毕并返回的,闭包必须要逃逸掉,以便异步操作的回调。
逃逸闭包一般用于异步函数的回调,比如网络请求成功的回调和失败的回调。语法:在函数的闭包行参前加关键字“@escaping”。
//例1
func doSomething(some: @escaping () -> Void){
//延时操作,注意这里的单位是秒
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 1) {
//1秒后操作
some()
}
print("函数体")
}
doSomething {
print("逃逸闭包")
} //例2
var comletionHandle: ()->String = {"约吗?"} func doSomething2(some: @escaping ()->String){
comletionHandle = some
}
doSomething2 {
return "叔叔,我们不约"
}
print(comletionHandle()) //将一个闭包标记为@escaping意味着你必须在闭包中显式的引用self。
//其实@escaping和self都是在提醒你,这是一个逃逸闭包,
//别误操作导致了循环引用!而非逃逸包可以隐式引用self。 //例子如下
var completionHandlers: [() -> Void] = []
//逃逸
func someFunctionWithEscapingClosure(completionHandler: @escaping () -> Void) {
completionHandlers.append(completionHandler)
}
//非逃逸
func someFunctionWithNonescapingClosure(closure: () -> Void) {
closure()
} class SomeClass {
var x = 10
func doSomething() {
someFunctionWithEscapingClosure { self.x = 100 }
someFunctionWithNonescapingClosure { x = 200 }
}
}
自动闭包
顾名思义,自动闭包是一种自动创建的闭包,封装一堆表达式在自动闭包中,然后将自动闭包作为参数传给函数。而自动闭包是不接受任何参数的,但可以返回自动闭包中表达式产生的值。
自动闭包让你能够延迟求值,直到调用这个闭包,闭包代码块才会被执行。说白了,就是语法简洁了,有点懒加载的意思。
var array = ["I","have","a","apple"]
print(array.count)
//打印出"4" let removeBlock = {array.remove(at: 3)}//测试了下,这里代码超过一行,返回值失效。
print(array.count)
//打印出"4" print("执行代码块移除\(removeBlock())")
//打印出"执行代码块移除apple" 这里自动闭包返回了apple值 print(array.count)
//打印出"3"
Swift3.0 闭包整理的更多相关文章
- Swift3.0 函数闭包与OC Block
刚接触Swift,如有不对的点,欢迎指正.转载请说明出处 定义一个基本函数 //定义一个函数,接收一个字符串,返回一个String类型的值 func test(name:String) -> S ...
- Swift3.0 函数闭包与 Block
刚接触Swift,如有不对,欢迎指正 Swift中定义一个基本函数 //定义一个函数,接收一个字符串,返回一个String类型的值 func test(name:String) -> Strin ...
- 关于for循环------swift3.0
在程序开发当中,for循环使用的频率无疑是最高的.常用的swift循环是递增式遍历.当然各种循环,swift都能办到.但其大多采用关键字形式实现,大部分开发者更喜欢直接使用C式循环代码.在swift3 ...
- swift3.0的改变
Swift在这2年的时间内,发展势头迅猛,在它开源后,更是如井喷一样,除了 iOS.mac 平台,还支持了 Linux. 而今年下半年, Swift 3.0 也会随之发布.https://github ...
- Swift3.0服务端开发(五) 记事本的开发(iOS端+服务端)
前边以及陆陆续续的介绍了使用Swift3.0开发的服务端应用程序的Perfect框架.本篇博客就做一个阶段性的总结,做一个完整的实例,其实这个实例在<Swift3.0服务端开发(一)>这篇 ...
- iOS开发之资讯类App常用分类控件的封装与实现(CollectionView+Swift3.0+)
今天博客中,我们就来实现一下一些常用资讯类App中常用的分类选择的控件的封装.本篇博客中没有使用到什么新的技术点,如果非得说用到了什么新的技术点的话,那么勉强的说,用到了一些iOS9以后UIColle ...
- 突然兴起复习一下Swift3.0
/// 参考Swift3.0.1文档 /// 摘录来自: Apple Inc. "The Swift Programming Language (Swift 3.0.1)". iB ...
- swift3.0 自定义键盘
...绕了一大圈,又绕回原生来了,今天,学习一下swift3.0语法下的自定义键盘.效果图如下: 其实,很简单,只需要把UITextView(或者UITextField)的inputView属性设置为 ...
- Swift3.0 功能一(持续更新)
修改项目名称两种方式 1.Bundle name 2.Bundle display name try 三种处理异常的方式 // 在swift中提供三种处理异常的方式 // 方式一:try方式 程序员手 ...
随机推荐
- BZOJ 2324 (有上下界的)费用流
思路: 先跑一遍Floyd 更新的时候map[i][j]=map[i][k]+map[k][j] k需要小于i或j 正常建边: 把所有点 拆点-> i,i+n add(x,y,C,E)表示x ...
- NFA
任意正则表达式都存在一个与之对应的NFA,反之亦然. 正则表达式 ((A*B|AC)D)对应的NFA(有向图), 其中红线对应的为该状态的ε转换, 黑线表示匹配转换 我们定义的NFA具有以下特点: 正 ...
- 纯CSS3文字Loading动画特效
纯CSS3文字Loading动画特效是一款个性的loading文字加载动画. 在线演示本地下载
- art-template简单使用
art-template是一款较通用的前端模板引擎. 简单的使用方法如下: 具备3个要素 1)模板 <script type="text/template" id=" ...
- javascript实现选项卡切换的4种方法
方法一:for循环+if判断当前点击与自定义数组是否匹配 <html lang="en"> <head> <meta charset="UT ...
- PowerDesigner 逆向工程 Could not Initialize JavaVM!
原项目的大量的表,使用PowerDesigner 进行逆向工程.提示Could not Initialize JavaVM! 网上找到原因,PowerDesigner 不可以使用64位JDK环境! 有 ...
- 杭电 2035 人见人爱A^B【快速幂取模】
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2035 解题思路:这一题数据不大,可以用同余来做,也可以用快速幂来做 反思:定义成 #include&l ...
- Python爬虫1-----urllib模块
1.加载urllib模块的request from urllib import request 2.相关函数: (1)urlopen函数:读取网页 webpage=request.urlopen(ur ...
- mongodb 和 mongoose 初探
mongodb MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的. 1. 安装相关 1.1 下载 官网下载地址 :官网下载社区版 1.2 安 ...
- P3369 【模板】普通平衡树 (splay 模板)
题目描述 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作: 插入x数 删除x数(若有多个相同的数,因只删除一个) 查询x数的排名(排名定义为比当前数小的数的个数+1.若有多 ...