目录
闭包表达式
/// 一、闭包表达式
func closureExpression(){
/*
在Swift中,可以通过func定义一个函数,也可以通过闭包表达式定义一个函数
*/
//1、函数作为参数
do{
func execute (_ x:Int,_ y:Int,fn:(Int,Int)->Int){
print(fn(x,y))
}
func sum (x:Int,y:Int)->Int{ x+y }
execute(10, 20, fn: sum)//30
}
//2、闭包表达式作为参数
do{
/*
//闭包表达式
{ (参数列表) -> 返回值类型 in
函数体代码
}
{ (x:Int,y:Int)->Int in
return x + y
}
*/
func execute (_ x:Int,_ y:Int,fn:(Int,Int)->Int){
print(fn(x,y))
}
//方式一:
execute(11, 22, fn:{(x:Int,y:Int)->Int in return x+y})//33
//简写
execute(11, 22, fn: {(x:Int,y:Int) in return x+y})//33
execute(11, 22, fn: {x,y in return x+y})//33
execute(11, 22, fn: {x,y in x+y })//33
//方式二:简写 $0 代表第一个参数
execute(12, 23, fn:{ $0 + $1 })//35
}
//3:尾随闭包 闭包作为最后一个参数
do{
/*
如果将一个很长的闭包表达式作为函数的最后一个实参,使用尾随闭包可以增强函数的可读性
尾随闭包是一个被书写在函数调用括号外面(后面)的闭包表达式
*/
func execute (_ x:Int,_ y:Int,fn:(Int,Int)->Int){
print(fn(x,y))
}
execute(10, 20){ x, y in x+y }//30
execute(14, 24){ $0+$1 }//38
/*
如果闭包表达式是函数的唯一实参,而且使用了尾随闭包的语法,那就不需要在函数名后边写圆括号
*/
func execute2 ( fn:(Int,Int)->Int ){
print(fn(10,20))
}
execute2 { $0 + $1}
}
//4、闭包表达式
do{
//let fn:(Int,Int)->Int = {(v1:Int,v2:Int)->Int in return v1+v2}
//let fn:(Int,Int)->Int = {v1,v2 in v1+v2}
let fn:(Int,Int)->Int = {$0+$1}
print(fn(1,2))//3
//let sumPrint:(Int,Int)->Void = {(x:Int,y:Int)->Void in print("x + y = ")}
let sumPrint:(Int,Int)->Void = {print("x + y = ",$0+$1)};
sumPrint(3,6)//x + y = 9
}
}
闭包表达式在数组中应用
/// 二、闭包表达式在数组中应用
func arrAnaly() {
//1、默认方式
do{
var arr:Array = [10,1,4,20,99]
arr.sort()
print(arr)//[1, 4, 10, 20, 99]
}
//2、使用尾随闭包
do{
var arr:Array = [10,1,4,20,99]
arr.sort{(i1:Int,i2:Int)->Bool in return i1 > i2}
print(arr)//[99, 20, 10, 4, 1]
}
//3、使用尾随闭包
do{
var arr:Array = [10,1,4,20,99]
arr.sort(){i1,i2 in i1 > i2}
print(arr)//[99, 20, 10, 4, 1]
}
//4、使用尾随闭包
do{
var arr:Array = [10,1,4,20,99]
arr.sort(){$0>$1}
print(arr)//[99, 20, 10, 4, 1]
}
}
闭包
/// 三、闭包(闭包与闭包表达式不同 是两个概念)
func closureAnaly(){
//定义一个函数类型
typealias Fn = (Int)->Int
/**
一个函数和它所捕获的变量/常量环境组合起来称为闭包
一般指定义在函数内部的函数
一般它所捕获的是外层函数的局部变量/常量
如:
getFun内部 有一个变量num 有一个函数plus 并且 plus捕获了变量num
num和plus组成的环境这就是闭包
*/
func getFn()->Fn{
//断点打到此处查看汇编 调用了malloc函数 证明在堆空间申请了内存
//也说明了为什么num销毁后 调用fn(1)还能获取到值 此时获取到的是堆空间相应内存的值
//此时 查看寄存器rax 可以得到 申请的内存地址
//并将立即数 $0x0写入了申请的这块内存
var num = 0
func plus(_ i:Int)->Int{
num+=i
//断点打到此处 可以查看相应的内存内数据发生的变化
return num
}
return plus
}
let fn1 = getFn()
print(fn1(1))//1
print(fn1(3))//4
print(fn1(5))//9
let fn2 = getFn()
print(fn2(2))//2
print(fn2(4))//6
print(fn2(6))//12
// (lldb) register read rax
// rax = 0x0000000100579440
// (lldb) memory read/5xg 0x0000000100579440
// 0x100579440: 0x0000000100010ad0 0x0000000200000002
// 0x100579450: 0x0000000000000001 0x00007fff55bef010
// 0x100579460: 0x00007fff8f631fe0
// (lldb) memory read/5xg 0x0000000100579440
// 0x100579440: 0x0000000100010ad0 0x0000000200000002
// 0x100579450: 0x0000000000000004 0x00007fff55bef010
// 0x100579460: 0x00007fff8f631fe0
// (lldb) memory read/5xg 0x0000000100579440
// 0x100579440: 0x0000000100010ad0 0x0000000200000002
// 0x100579450: 0x0000000000000009 0x00007fff55bef010
// 0x100579460: 0x00007fff8f631fe0
/**
可以把闭包想象成一个类的实例对象
内存在堆空间
捕获的局部变量/常量就是对象的成员(存储属性)
组成闭包的函数就是类内部定义的方法
*/
class getFnc{
var num = 0
func plus(_ i:Int) -> Int {
num+=i
return num
}
}
let fnc1 = getFnc()
print(fnc1.plus(1))//1
print(fnc1.plus(3))//4
print(fnc1.plus(5))//9
let fnc2 = getFnc()
print(fnc2.plus(2))//2
print(fnc2.plus(4))//6
print(fnc2.plus(6))//12
}
/// 四、闭包分析2
func closureAnaly2() {
typealias Fn = (Int)->(Int,Int)
func getFns()->(Fn,Fn){
var num1 = 0
var num2 = 0
func plus(_ i:Int)->(Int,Int){
num1 += i
num2 += i<<1//位运算优先级高
return (num1,num2)
}
func minus (_ i:Int) -> (Int,Int){
num1 -= i
num2 -= i<<1//位运算优先级高
return (num1,num2)
}
return (plus,minus)
}
let (p,m) = getFns()
print(p(5))//(5, 10)
print(m(4))//(1, 2)
print(p(3))//(4, 8)
print(m(2))//(2, 4)
}
行者常至,为者常成!