JHHK

欢迎来到我的个人网站
行者常至 为者常成

6、闭包表达式(一)

目录

闭包表达式

/// 一、闭包表达式
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)
}

行者常至,为者常成!





R
Valine - A simple comment system based on Leancloud.