美文网首页
swift3.1 函数和闭包

swift3.1 函数和闭包

作者: 岁月蹉跎繁华落寞 | 来源:发表于2017-04-25 23:33 被阅读0次

    函数

    func greet(person: String, alreadyGreeted: Bool) -> String {
        if alreadyGreeted {
            return greetAgain(person: person)
        } else {
            return greet(person: person)
        }
    }
    print(greet(person: "Tim", alreadyGreeted: true))
    // Prints "Hello again, Tim!"
    
    //没有返回值的函数,实际上返回了Void, 一个空的元组()。
    
    //返回多个值
    func minMax(array: [Int]) -> (min: Int, max: Int) {
        var currentMin = array[0]
        var currentMax = array[0]
        for value in array[1..<array.count] {
            if value < currentMin {
                currentMin = value
            } else if value > currentMax {
                currentMax = value
            }
        }
        return (currentMin, currentMax)
    }
    
    //返回可选型的元组 (Int, Int)? is different from a tuple that contains optional types such as (Int?, Int?). 
    
    摘录来自: Apple Inc. “The Swift Programming Language (Swift 3.1)”。 iBooks. 
    func minMax(array: [Int]) -> (min: Int, max: Int)? {
        if array.isEmpty { return nil }
        var currentMin = array[0]
        var currentMax = array[0]
        for value in array[1..<array.count] {
            if value < currentMin {
                currentMin = value
            } else if value > currentMax {
                currentMax = value
            }
        }
        return (currentMin, currentMax)
    }
    
    //函数辨识标签和参数名
    
    

    闭包

    //一般形式
    let calAdd:(Int,Int)->(Int) = {
        (a:Int,b:Int) -> Int in
        return a + b
    }
    print(calAdd(100,150))
     
    //Swift可以根据闭包上下文推断参数和返回值的类型,所以上面的例子可以简化如下
    let calAdd2:(Int,Int)->(Int) = {
        a,b in  //也可以写成(a,b) in
        return a + b
    }
    print(calAdd2(150,100))
    //上面省略了返回箭头和参数及返回值类型,以及参数周围的括号。当然你也可以加括号,为了好看点,看的清楚点。(a,b)
     
    //单行表达式闭包可以隐式返回,如下,省略return
    let calAdd3:(Int,Int)->(Int) = {(a,b) in a + b}
    print(calAdd3(50,200))
     
    //如果闭包没有参数,可以直接省略“in”
    let calAdd4:()->Int = {return 100 + 150}
    print("....\(calAdd4())")
     
    //这个写法,我随便写的。打印出“我是250”
    //这个是既没有参数也没返回值,所以把return和in都省略了
    let calAdd5:()->Void = {print("我是250")}
    calAdd5()
    
    //也可以关键字“typealias”先声明一个闭包数据类型。类似于OC中的typedef起别名
    typealias AddBlock = (Int, Int) -> (Int)
     
    let Add:AddBlock = {
        (c,d) in
        return c + d
    }
     
    let Result = Add(100,150)
    print("Result = \(Result)")
    
    尾随闭包
    //若将闭包作为函数最后一个参数,可以省略参数标签,然后将闭包表达式写在函数调用括号后面
    func testFunction(testBlock: ()->Void){
        //这里需要传进来的闭包类型是无参数和无返回值的
        testBlock()
    }
    //正常写法
    testFunction(testBlock: {
        print("正常写法")
    })
    //尾随闭包写法
    testFunction(){
        print("尾随闭包写法")
    }
    //也可以把括号去掉,也是尾随闭包写法。推荐写法
    testFunction { 
        print("去掉括号的尾随闭包写法")
    }
    
    //值捕获
    func captureValue(sums amount:Int) -> ()->Int{
        var total = 0
        func incrementer()->Int{
            total += amount
            return total
        }
        return incrementer
    }
     
    print(captureValue(sums: 10)())
    print(captureValue(sums: 10)())
    print(captureValue(sums: 10)())
    //打印"10 10 10"
    
    let referenceFunc = captureValue(sums: 10)
    print(referenceFunc())
    print(referenceFunc())
    print(referenceFunc())
    //打印"10 20 30"
    
    func captureValue2(sums amount:Int) -> ()->Int{
        var total = 0
        let AddBlock:()->Int = {
            total += amount
            return total
        }
        return AddBlock
    }
     
    let testBlock = captureValue2(sums: 100)
    print(testBlock())
    print(testBlock())
    print(testBlock())
    
    //由上面的例子都可以证得,函数和闭包都是引用类型
    
    逃逸闭包
    当一个闭包作为参数传到一个函数中,需要这个闭包在函数返回之后才被执行,我们就称该闭包从函数种逃逸。一般如果闭包在函数体内涉及到异步操作,但函数却是很快就会执行完毕并返回的,闭包必须要逃逸掉,以便异步操作的回调。
    
    //例1
    func doSomething(some: @escaping () -> Void){
        //延时操作,注意这里的单位是秒
        DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 1) {
            //1秒后操作
            some()
        }
        print("函数体")
    }
    doSomething {
        print("逃逸闭包")
    }
     
    //例2
    var comletionHandle: ()->String = {"约吗?"}
     
    func doSomething2(some: @escaping ()->String){
        comletionHandle = some
    }
    doSomething2 {
        return "叔叔,我们不约"
    }
    print(comletionHandle())
     
    //将一个闭包标记为@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 }
        }
    }
    
    自动闭包
    顾名思义,自动闭包是一种自动创建的闭包,封装一堆表达式在自动闭包中,然后将自动闭包作为参数传给函数。而自动闭包是不接受任何参数的,但可以返回自动闭包中表达式产生的值。
    自动闭包让你能够延迟求值,直到调用这个闭包,闭包代码块才会被执行。说白了,就是语法简洁了,有点懒加载的意思。
    
    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"
    

    相关文章

      网友评论

          本文标题:swift3.1 函数和闭包

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