博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
闭包block多种应用方式
阅读量:6970 次
发布时间:2019-06-27

本文共 2925 字,大约阅读时间需要 9 分钟。

hot3.png

闭包是一个十分强大的功能,灵活多变,便于使用;实际上闭包是一种匿名的函数.

其类型和对应的函数类型保持一致.

使用闭包,我们可以动态的改变函数或方法中的代码,从而适应不同环境下的要求.

1.闭包的形式

  1. {    (形参列表) ->返回值类型  in  
  2.           //其他代码    
  3. }  

对比函数的定义,如下

  1. func 函数名(参数列表) [ - > 返回值类型]  
  2. {  
  3.     //函数体  
  4. }  

我们可以看到,闭包与函数的主要区别是 少了  func  函数名这一块;也就是说,函数与闭包的主要区别就是闭包是匿名的.

闭包示例:

  1. {  
  2.     (a:Int,b:Int)->Int in  
  3.   
  4.     return a+b  
  5.       
  6. }  

2.闭包的使用,闭包赋值给一个变量之后,该变量可以直接当函数使用

(1)定义一个闭包,功能是计算两个数之和,使用一个变量来接受该闭包.

  1. var plus =  
  2. {  
  3.     (a:Int,b:Int)->Int in  
  4.   
  5.     return a+b  
  6.       
  7. }  

对于我们的写法系统则默认处理 plus为一个函数,见下图

\

(2)使用闭包,当做函数来使用闭包变量

  1. var c = plus(2,3)  
  2. println(c)  

当然我们也可以把 plus变量 用来接收其他的闭包

(3)闭包的外部形参名是没有作用的

和函数类似,闭包也可以使用外部形参名,但是闭包的外部形参名是没有任何作用的,我们使用闭包时,不能输入对于的外部形参名,否则会报错

  1. var plus =  
  2. {  
  3.     (#a:Int,第二个参数 b:Int)->Int in  
  4.   
  5.     return a+b  
  6.       
  7. }  

对于上面的代码,我们需要使用如下的方式使用;不能传入外部形参名

  1. var c = plus(22,3)  
  2. println(c)  

而对于我们愿景来说使用:

  1. var c2 = plus(a:1,第二个参数 :3)  

反而会报错!这也许在后期的版本中可能会有所改变;但是如今,我们最好还是别画蛇添足了!

(4)定义完闭包之后直接调用该闭包

闭包还支持定义以后直接传入对应的参数来调用该闭包,调用闭包时需要使用括号.

如下面的代码,在定义完代码之后直接调用该闭包,结果返回给  plus变量

  1. var plus =  
  2. {  
  3.     (a:Int,b:Int)->Int in  
  4.   
  5.     return a+b  
  6.       
  7. }(2,3)  

输出:

  1. 5  

3.闭包的类型推断

闭包的类型,实际上一种函数类型;其类型可以根据用来接收闭包的变量的类型或者实参的类型来自动推断出  闭包对应的类型.

(1)闭包根据变量是 函数类型的 来推断其 参数类型,返回值类型

  1. var plus2:(Int,Int)->Int =  
  2. {  
  3.     (a,b) in  
  4.       
  5.     return a+b  
  6.       
  7. }  

或者省略括号

  1. var plus2:(Int,Int)->Int =  
  2. {  
  3.     a,b in  
  4.       
  5.     return a+b  
  6.       
  7. }  

此时的plus2是一个函数,所以我们使用如下方式调用闭包

  1. println(plus2(3,4))  

由于plus2的类型是  (Int,Int)->Int函数类型,那么 闭包可自动推断  出  参数  a,b的类型是  Int,返回值是  Int类型

(2)闭包根据传入的实参类型来自动推断闭包类型

  1. var app:Int =  
  2. {  
  3.     a,b in  
  4.       
  5.     return a+b  
  6. }(111,222)  

输出:对应的app的值

  1. println(app)  

我们在定义闭包后直接调用闭包需要传入实参,闭包可以根据实参的类型来推断

 其中  a,b参数的类型;返回值类型和 app的类型一致 推断出是 Int类型

4.闭包 省略 return 语句

当 闭包的内容只有一行,且该行语句是返回一个值,那么此时 return 可以省略

  1. var plus3:(Int,Int)->Int =  
  2. {  
  3.     a,b in  
  4.       
  5.     a+b  
  6.       
  7. }  

如上面的闭包省略了 形参类型和 return ;

该闭包只有 一行语句且该语句就是闭包的返回值

5.省略形参名和 in 关键字

Swift不仅可以省略上述情况的一些东西,还允许省略  形参名 和  in;

Swift可以 通过  $0  ,$1  ...来引用第一个 ,第二个形参 ,第N个形参...

  1. var app3:Int =  
  2. {  
  3.   return $0*$0  
  4. }(111)  

$0代表 $0

或者省略 return 

  1. var app2:Int =  
  2. {  
  3.     $0*$1  
  4. }(111,222)  

 

$1代表222

原则是 闭包 可以根据 实参,或者 接收该闭包的变量的类型来自动推断类型

6.尾随闭包

(1)闭包作为函数的一个参数

首先我们来定义一个 参数带有 函数类型的 函数

  1. func myFunc(#a:Int,#b:Int,#fun:(Int,Int)->Int)->Int  
  2. {  
  3.       
  4. }  

参数 fun是一个 函数类型的参数,我们可以传入一个函数 或者  闭包

完整定义

  1. func myFunc(#a:Int,#b:Int,#fun:(Int,Int)->Int)->Int  
  2. {  
  3.     var c = fun(a,b)  
  4.     return c  
  5. }  

调用时传入一个  闭包 

  1. var d = myFunc(a: 11, b: 22, fun: {  return $0+$1})  

或者:

  1. var d = myFunc(a: 11, b: 22, fun: {  $0+$1})  

fun闭包完全可以根据 myFunc形参类型来 省略 fun的 类型甚至 省略  return (因为只有一行语句)

(2)当函数的最后一个参数是函数类型时,可以使用尾随闭包,简化写法

可以看到步骤1  调用的方式 是  :

  1. myFunc(a:,b:,fun:{闭包体})   

此种情况使用尾随闭包则可以写的更简洁

改为

  1. myFunc(a:,b:)  
  2. {  
  3.       //闭包体  
  4. }  

 

  1. var cc = myFunc(a: 1, b: 2){$0+$1}  

如上代码,  返回值  $0+$1的闭包; 

因为  a,b是属于  myFunc函数的 ,所以在闭包中 体中 并不知道 a,b这几个变量,只能使用  $0的形式

  1. 尾随闭包: 就是当函数的最后一个参数是函数类型时,调用函数 时,可传入一个闭包 ,该闭包可以放在 圆括号之外  

7.捕获所对应的作用域的值

闭包可以访问 其所处的上下文(还有全局的)的变量和常量,称之为 捕获

  1. var dd = 2  
  2.   
  3. func myFunc(#a:Int,#b:Int,#fun:(Int,Int)->Int)->Int  
  4. {  
  5.       
  6.     var aa = 22, bb = 33  
  7.       
  8.     var c = fun(dd,bb)  //闭包可以访问  aa,bb  
  9.     return c  
  10. }  

 

如上代码 ,闭包 fun可以访问    全局变量 dd;

当然也可以访问 bb ,此称之为 捕获.

8.闭包的类型

Swift闭包 和 Oc的闭包类似,都是引用类型的;所以我们把复制 闭包变量时,实际上是复制的对应的指针; 复制的 副本 和 源 闭包变量指向同一变量

9.闭包的用途

闭包可以使用在  网络异步任务  , 界面传值  ,GCD ,数组排序,动画,组件封装 等地方;

灵活的使用闭包,可以让我们事半功倍

转载于:https://my.oschina.net/fadoudou/blog/699159

你可能感兴趣的文章
jquery下拉导航菜单(扩展很方便)
查看>>
js数字比较【牢记】
查看>>
如何实现密码域灰色默认提示?
查看>>
zabbix
查看>>
JAVA--虚函数,抽象函数,抽象类,接口
查看>>
解决 You could try using --skip-broken to work around the problem
查看>>
php清楚squid缓存
查看>>
openstack Folsom版本安装
查看>>
Cisco Catalyst 交换机一直处于rommon模式无法启动IOS问题的解决
查看>>
java io以及unix io模型
查看>>
syslog及syslog-ng详解
查看>>
UITableViewController
查看>>
我的友情链接
查看>>
Java源码分析系列之HttpServletRequest源码分析
查看>>
如何通过命令行创建和设置一个MySQL用户
查看>>
WPF DrawingContext Pen
查看>>
Wordpress+LNMP 环境搭建
查看>>
小步快跑是这样玩的(下)
查看>>
rsync工作方式介绍03
查看>>
Windows 7蓝屏自动重启,无法修复的处理办法
查看>>