美文网首页
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 函数和闭包

    函数 闭包

  • rust 闭包与同步

    rust 闭包与同步 rust 闭包 rust闭包中主要包括两个部分,闭包参数和闭包环境变量。闭包函数和函数参数使...

  • 函数对象和闭包

    函数对象和闭包 一) 函数对象 示例: 二)函数嵌套 三)闭包函数

  • 面试题(day-2)

    1 ,什么是闭包?闭包有什么好处?使用闭包要注意什么? 闭包:函数嵌套函数,内部函数可以引用外部函数的参数和变量,...

  • Swift-闭包

    闭包的特点:一个函数有权访问另外一个函数内的变量和参数 闭包—匿名函数 结尾闭包 衍生 内容捕获 闭包和函数是引用类型

  • 闭包函数

    闭包函数 闭包,又称闭包函数或者闭合函数,其实和嵌套函数类似,不同之处在于,闭包中外部函数返回的不是一个具体的值,...

  • php之闭包函数(Closure)

    php闭包函数(Closure) JS闭包 js和php闭包使用和区别

  • 变量

    闭包: 什么是闭包? 函数嵌套函数,内部函数可以引用外部函数的参数和变量,参数和变量不会被垃圾机构回收; 用闭包做...

  • 变量和函数、闭包

    闭包: 什么是闭包? 函数嵌套函数,内部函数可以引用外部函数的参数和变量,参数和变量不会被垃圾机构回收; 用闭包存...

  • 13_day变量和函数、闭包

    闭包: 什么是闭包? 函数嵌套函数,内部函数可以引用外部函数的参数和变量,参数和变量不会被垃圾机构回收; 用闭包做...

网友评论

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

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