美文网首页
2.3、闭包

2.3、闭包

作者: 艾希_可可 | 来源:发表于2017-06-28 09:58 被阅读7次

    //: Playground - noun: a place where people can play

    import UIKit

    /*

     闭包

     闭包(Closures)是自包含的功能代码块,可以在代码中使用或者用来作为参数传值。

     闭包相当于oc中的block,语法格式不一样,但作用是一样的

     主要是用于两个类之间的异步回调

     闭包可看作是int、float一样是一种数据类型,一种可以作为参数传递的数据类型

     格式:

     {

     (参数)-> 返回值类型 in

     执行语句

     }

     */

    //(1)一般形式

    letcalAdd:(Int,Int)->(Int) = {

        (a:Int,b:Int)->Intin

        returna + b

    }

    calAdd(100,200)

    //(2)简化形式

    //swift可以根据闭包上下文推断参数和返回值的类型,所以上面的例子可以简化如下

    letcalAdd2:(Int,Int)->(Int) = {

        a,bin  // 也可以写成(a,b) in

        returna + b

    }

    calAdd2(10,20)//省略了返回箭头和返回值类型,以及参数周围的括号

    //(3)单行表达式闭包可以隐式返回,如下,省略return

    letcalAdd3:(Int,Int)->(Int) = {(a,b)ina + b }

    calAdd3(20,30)

    //(4)如果闭包没有参数,可以直接省略“in”

    letcalAdd4:()->Int= {return1+2}

    print("\(calAdd4())")

    //(5)最简单闭包 这个是既没有参数也没有返回值,所以return和in都省略了

    letcalAdd5:()->Void= {

        print("既没有参数也没有返回值,所以return和in都省略了")

    }

    //(6)闭包内嵌函数 函数表达式作为回调函数

    letsumMethod:(_a:Int,_b:Int)->(Int) = {

        (a,b) -> (Int)in

        varb = b

        funcchangeValue() -> (Int) {

            b += a

            returnb

        }

        return changeValue()

    }

    sumMethod(3, 4)

    //补充----------------神奇的下划线

    //1.格式化数字字面量

    //通过使用下划线能够提高数字字面量的可读性,比如:

    letpaddedDouble =123.000_001

    letoneMillion =1_000_000

    //2.忽略元组的元素值

    //当我们使用元组时,假设有的元素不须要使用。这时能够使用下划线将对应的元素进行忽略,比如:

    lethttp404Error = (404,"Not Found")

    let(_, errorMessage) =http404Error

    //3.忽略区间值

    letbase =3

    letpower =10

    varanswer =1

    for _ in 1...power {//只是为了算多次,不关心区间每一项的值

        answer *= base

    //    print(answer)

    }

    //4.忽略外部參数名

    //(1).忽略方法的默认外部參数名

    //在用法(类方法或者实例方法)时,方法的第二个參数名及兴许的參数名,默认既是内部參数名,又是外部參数名。假设不想提供外部參数名,能够在參数名前加入下划线来忽略外部參数名。

    varcount:Int=0

    funcincrementBy(amount:Int, numberOfTimes:Int){

        count+= amount * numberOfTimes

    }

    //在上面的代码中,方法incrementBy()中的numberOfTimes具有默认的外部參数名:numberOfTimes,假设不想使用外部參数名能够使用下划线进行忽略,代码能够写为(只是为了提高代码的可读性,一般不进行忽略):

    varcount2:Int=0

    funcincrementBy(amount:Int,_numberOfTimes:Int) {

        count2+= amount * numberOfTimes

    }

    //(2).忽略具有默认值的參数的外部參数名

    //当函数(或者方法)的參数具有默认值时,Swift自己主动为该參数提供与參数名一致的默认外部參数名,因此在进行函数调用的时候,要提供默认參数名。能够使用下划线进行忽略默认外部參数名(可是不推荐忽略外部參数名。这主要是为了调用的时候能够方便地知道每一个參数的含义)

    funcjoin(s1:String, s2:String, joiner:String=" ") ->String{

        returns1 + joiner + s2

    }

    join(s1:"hello", s2:"swift", joiner:"-")

    //假设不想使用默认外部參数名,能够进行例如以下改动:

    funcjoin2(s1:String, s2:String,_joiner:String=" ") ->String{

        returns1 + joiner + s2

    }

    join2(s1: "hello", s2: "world", "-")

    join2(s1: "good", s2: "morning")

    //(7)闭包内嵌闭包

    letstrFormat:(_str1:String,_str2:String,_x:Int) ->Int= {

        (str1,str2,x)in

        letcalcute:(Int)->Int= {

            return$0

        }

        returncalcute(x)

    }

    strFormat("a", "b", 5)

    //归纳:闭包类型是由参数和返回值决定,和函数一样

    //(8)起别名 关键字 typealias声明一个闭包数据类型,类似于OC中的typedef别名

    typealiasAddBlock = (Int,Int)->(Int)

    letadd:AddBlock= {

        (a,b)in

        returna+b

    }

    add(5,5)

    //(9)尾随闭包 若将闭包作为最后一个参数,可以省略参数标签,然后将闭包表达式写在函数调用括号后面

    functestFunction(testBlock:()->Void){

        testBlock()

    }

    testFunction(testBlock: {

        print("正常写法")

    })

    testFunction(){

        print("尾随闭包写法")

    }

    testFunction {

        print("去掉括号的尾随闭包写法")

    }

    //值捕获

    //闭包可以定义在其被定义的上下文中捕获常量或者变量,swift中可以捕获值的形式比如嵌套函数,也就是定义在其他函数的函数体内

    //逃逸闭包

    //当一个闭包作为参数传到一个函数中,需要这个闭包在函数返回之后才被执行,我们就称该闭包从函数中逃逸,一般如果闭包在函数体内涉及到异步操作,但函数却是很快就会执行完毕并返回的,闭包必须要逃逸掉,以便异步操作的回调

    //逃逸闭包一般用于一部分回调函数的回调,比如网络请求成功的回调和失败的回调,语法仔函数的闭包行前加关键字@escaping

    //示例1

    funcrequestData(urlStrings :String,parameter : [String:Any],successData :@escaping(Any?)->(Void),failData :@escaping(Any?)->(Void)) {

        successData("请求成功")

        failData("请求失败")

        print("函数体")

    }

    //示例2

    varcomletionHandle:()->String= {"喜欢😍看电影吗?"}

    funcdoSomething(some:@escaping()->String){

        comletionHandle = some

    }

    doSomething{

        return "喜欢"

    }

    print(comletionHandle())

    //自动闭包

    //顾名思义,自动闭包是一种自动创建的闭包,封装一堆表达式在自动闭包中,然后将自动闭包作为参数传给函数。而自动闭包是不接受任何参数的,但可以返回自动闭包中表达式产生的值。

    //自动闭包让你能够延迟求值,直到调用这个闭包,闭包代码块才会被执行

    var array = ["I","have","a","apple"]

    print(array.count)

    letremoveBlock = {

        array.remove(at:3)

    }

    print(array.count)

    print("执行代码块移除\(removeBlock())")

    //打印出"执行代码块移除apple" 这里自动闭包返回了apple值

    print(array.count)

    //闭包捕获值

    funcgetIncFunc(inc:Int) -> (Int) ->Int

    {

        varmax =10

        funcincFunc(x :Int) ->Int{

            print("incFunc函数结束")

            returninc + x

    //        max += 1

    //        return max + x

        }

        // 当执行到这一句时inc参数就应该被释放了, 但是由于在内部函数中使用到了它, 所以它被捕获了

        // 同理, 当执行完这一句时max变量就被释放了,但是由于在内部函数中使用到了它, 所以它被捕获了

        print("getIncFunc函数结束")

        return incFunc

    }

    // 被捕获的值会和与之对应的方法绑定在一起, 同一个方法中的变量会被绑定到不同的方法中

    print("-------------")

    letincFunc =getIncFunc(inc:5)

    print(incFunc(2))

    print(incFunc(5))

    letincFunc2 =getIncFunc(inc:5)

    print(incFunc2(5))

    print("-------------")

    //练习page707

    //1、哪个句子最好描述一个闭包?3

    //A最后一个函数在swift文件中。

    //B可以全局执行的匿名函数。

    //C可以作为变量存储或作为参数传递的代码块。

    //D可以在范围内执行的指定代码块。

    //4、以下哪一个不是一个接受闭包作为参数的函数?4

    //5、5

    //A map()返回与原始数组相同长度的新数组。

    //B map()是一个对象的集合映射到其他对象的集合

    //C、map()对数组中的每个对象执行一个闭包。

    funcsumd(numberss:[Int]) ->Int{

        return 5

    }

    sumd(numberss: [2])

    sumd(numberss: [11])

    相关文章

      网友评论

          本文标题:2.3、闭包

          本文链接:https://www.haomeiwen.com/subject/alaycxtx.html