前语

函数在 Swift 中是很强壮的东西。可将函数分配给变量、将函数传递给函数,甚至从函数回来函数。
如:将函数分配给变量

func greetUser() {
    print("xxxxxxx!")
}
greetUser()    //调用函数
var greetCopy = greetUser    // 创立该函数的副本并调用该副本;仿制函数时,不要在其后写括号
greetCopy() 

闭包表达式

当然,咱们也能够不需要独自创立一个函数。所以:

let sayHello = {
    print("Hi xxxxxx!")
}
sayHello() 

咱们能够随时传递和调用的一段代码。 它实际上是一个没有称号的,不带参数且不回来值的函数。

在Swift中,它叫 闭包表达式。

  • 带参数和回来值的闭包
let sayHello = { (name: String) -> String in
    "Hi (name)!"
}  

其中,in是关键字,位于闭包的参数和回来类型之后。 in用于标记 参数和回来类型的完毕,in之后的一切内容都是闭包自身的主体。

闭包在 Swift 中被广泛运用 。

从排序函数说起

数组的排序函数

let team = ["Gloria", "Suzanne", "Piper", "Tiffany", "Tasha"]
let sortedTeam = team.sorted()
print(sortedTeam)  

sorted()实际上允许咱们 传递一个函数来创立自定义排序顺序,只需该函数 a) 承受两个字符串,b) 回来一个布尔值,sorted()就能够运用它。

好,先定义一个函数,作为sorted()的参数

func captainFirstSorted(name1: String, name2: String) -> Bool {
    if name1 == "Suzanne" {
        return true
    } else if name2 == "Suzanne" {
        return false
    }
    return name1 < name2
} 

传入

let arr = team.sorted(by: captainFirstSorted)
print(arr)  

以上都没有问题。

在Swift中,若A函数承受一个B函数作为参数,A函数并不关怀传入的函数参数是一个创立的func,或一个闭包。

好的,让咱们编写sorted()运用闭包进行调用的新代码:

let captainFirstTeam = team.sorted(by: { (name1: String, name2: String) -> Bool in
    if name1 == "Suzanne" {
        return true
    } else if name2 == "Suzanne" {
        return false
    }
    return name1 < name2
}) 

在这里,咱们不是传递一个函数,而是传递一个闭包————从by:到最后一行的)的一切内容都是闭包的一部分。

这样,咱们不需要独自编写一个新函数了。

Swift 中闭包最常见的原因之一是存储功能————“这是我期望你在某个时分做的一些工作,但不一定是现在。”
比方:延迟后运转一些代码。
动画完成后运转一些代码。
下载完成后运转一些代码。
当用户从菜单中选择一个选项时运转一些代码。

有了闭包,咱们能够将一些功能包装在一个变量中,然后将其存储在某个地方。咱们还能够从函数回来它,并将闭包存储在其他地方。

闭包语法

一个承受一个参数但不回来内容的闭包:

let payment = { (user: String) in
    print("Paying (user)…")
} 

一个承受一个参数并回来一个布尔值的闭包:

let payment = { (user: String) -> Bool in
    print("Paying (user)…")
    return true
}  

回来一个值而不承受任何参数

let payment = { () -> Bool in
    print("Paying an anonymous person…")
    return true
}  

跟随闭包和简练语法

上述的sorted函数中,其实咱们不需要指定两个参数的类型,由于它们有必要是字符串,而且咱们不需要指定回来类型,由于它有必要是布尔值。因而,咱们能够将代码重写为:

let captainFirstTeam = team.sorted { name1, name2 in
    if name1 == "Suzanne" {
        return true
    } else if name2 == "Suzanne" {
        return false
    }
    return name1 < name2
}  

另外, Swift 为咱们提供的专门命名的值:$0$1,分别用于第一个和第二个参数。 所以,咱们甚至不需要指定参数了:

let captainFirstTeam = team.sorted {
    if $0 == "Suzanne" {
        return true
    } else if $1 == "Suzanne" {
        return false
    }
    return $0 < $1
}  

跟随闭包的 案例


func animate(duration: Double, animations: () -> Void) {
    print("Starting a (duration) second animation…")
    animations()
}  

没有跟随闭包的情况下调用该函数,如下所示:

animate(duration: 3, animations: {
    print("Fade out the image")
})  

用跟随闭包调用:

animate(duration: 3) {
    print("Fade out the image")
}  

代码简练了许多

  • 函数承受多个函数参数,在这种情况下您能够指定多个跟随闭包。

这里有一个承受三个函数参数的函数,每个参数不承受任何参数,也不回来任何内容:

func doImportantWork(first: () -> Void, second: () -> Void, third: () -> Void) {
    first()
    second()
    third() 
} 

调用它时,第一个跟随闭包与咱们现已运用过的相同,但第二个和第三个的格式不同:您完毕前一个闭包的大括号,然后写入外部参数称号和冒号,然后开始另一个支撑。

doImportantWork {
    print("This is the first work")
} second: {
    print("This is the second work")
} third: {
    print("This is the third work")
}