闭包

来源:互联网 发布:软件下载模板 编辑:程序博客网 时间:2024/06/05 01:37

闭包,closure,类似于OC中的Block,在swift中可作为参数,返回值,等各种处理

通常形式:

        let callAdd1 : (Int,Int) -> Int = {
            (a:Int,b:Int) -> Int in
            return a+b
        }

通常为了减少代码,不降低代码可读性,用下列格式即可。既能一眼看出闭包的参数,返回值,又能减少重复的定义类代码

        let callAdd:(Int,Int) -> Int = {
            (a,b) in
            return a+b
        }


swift中有类似于oc中命别名的方法,通常如下

        //定义一个无参无返回值的闭包类型

        typealias voidClosureType = ()->Void

以下定义了一个闭包类型,创建了一个该类型的闭包,然后调用了一个以该闭包作为参数的方法

        typealias voidClosureType = ()->Void
        
        let voidClosure : voidClosureType = {
            print("this is a void closure")
        }
        
        closureFunc(testClosure: voidClosure)
   
    
    func closureFunc(testClosure:()->Void) -> Void {
        print("this is a closure func")
        
        testClosure()

    }

调用带闭包参数的方法时,如果闭包参数是该方法的最后一个参数,则可以用尾随闭包的方法,例如:

方法是:

    func closureFunc(testClosure:()->Void) -> Void {
        print("this is a closure func")
        
        testClosure()
    }

通常调用该方法时,是这种写法:

        closureFunc(testClosure: {
            print("this is myselves fucetion closure")
        })

尾随闭包写法如下:

        closureFunc (){
            print("this is dai kuo hao de closure")
        }

也可以省略括号,就成了以下的写法,这是推荐的写法:

        closureFunc {
            print("jiji")
        }

闭包可以在其被定义的上下文中捕获常量或变量,类似于block也可以获取上面的变量。如下

func captureValue(sums amount:Int) -> ()->Int{
    var total = 0
    func incrementer()->Int{
        total += amount
        return total
    }
    return incrementer
}
闭包逃逸

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

逃逸闭包一般用于异步函数的回调,比如网络请求成功的回调和失败的回调。语法:在函数的闭包行参前加关键字“@escaping”。   

func doSomething(some:@escaping ()->Void) -> Void {
        //延迟一秒的操作
        DispatchQueue.main.asyncAfter(deadline: DispatchTime.now()+1) {
            some()
        }
        print("do someThing func return")
    }

//例2
var comletionHandle: ()->String = {"约吗?"}
 
func doSomething2(some: @escaping ()->String){
    comletionHandle = some
}
doSomething2 {
    return "叔叔,我们不约"
}
print(comletionHandle())

PS:handler的那个闭包,只是返回一个字符串。在方法中,调用了该闭包了,重新赋值了,运行完毕,并未运行闭包,后续才运行闭包,故要escaping

//将一个闭包标记为@escaping意味着你必须在闭包中显式的引用self。
//其实@escaping和self都是在提醒你,这是一个逃逸闭包,
//别误操作导致了循环引用!而非逃逸包可以隐式引用self。
上面的这三句话我并没有看懂,下面的栗子也没有看懂,后续在研究吧

//例子如下
var completionHandlers: [() -> Void] = []
//逃逸
func someFunctionWithEscapingClosure(completionHandler: @escaping () -> Void) {
    completionHandlers.append(completionHandler)
}
//非逃逸
func someFunctionWithNonescapingClosure(closure: () -> Void) {
    closure()
}
 
class SomeClass {
    var x = 10
    func doSomething() {
        someFunctionWithEscapingClosure { self.x = 100 }
        someFunctionWithNonescapingClosure { x = 200 }
    }
}

自动闭包

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

自动闭包让你能够延迟求值,直到调用这个闭包,闭包代码块才会被执行。说白了,就是语法简洁了,有点懒加载的意思。

PS:并搞不懂自动闭包的意思

var array = ["I","have","a","apple"]
print(array.count)
//打印出"4"
 
let removeBlock = {array.remove(at: 3)}//测试了下,这里代码超过一行,返回值失效。
print(array.count)
//打印出"4"
 
print("执行代码块移除\(removeBlock())")
//打印出"执行代码块移除apple" 这里自动闭包返回了apple值
 
print(array.count)
//打印出"3"


0 0
原创粉丝点击