2.3、闭包

//: 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、闭包)