Skip to main content

Swift闭包

note

Swift的闭包概念有点类似于JS的匿名函数。

语法

{(parameters) -> return type in
statements
}

实例

sorted方法

info

Swift 标准库提供了名为 sorted(by:) 的方法,会根据您提供的用于排序的闭包函数将已知类型数组中的值进行排序。

排序完成后,sorted(by:) 方法会返回一个与原数组大小相同,包含同类型元素且元素已正确排序的新数组。原数组不会被 sorted(by:) 方法修改。

sorted(by:)方法需要传入两个参数:

  • 已知类型的数组
  • 闭包函数,该闭包函数需要传入与数组元素类型相同的两个值,并返回一个布尔类型值来表明当排序结束后传入的第一个参数排在第二个参数前面还是后面。如果第一个参数值出现在第二个参数值前面,排序闭包函数需要返回true,反之返回 false
  • 不用闭包
let names = ["AT", "AE", "D", "S", "BE"]

// 使用普通函数(或内嵌函数)提供排序功能,闭包函数类型需为(String, String) -> Bool。
func backwards(s1: String, s2: String) -> Bool {
return s1 > s2
}
var reversed = names.sorted(by: backwards)

print(reversed)
  • 用闭包
let names = ["AT", "AE", "D", "S", "BE"]

var reversed = names.sorted( by: { $0 > $1 } )
print(reversed)
note

如果你在闭包表达式中使用参数名称缩写, 您可以在闭包参数列表中省略对其定义, 并且对应参数名称缩写的类型会通过函数类型进行推断。in关键字同样也可以被省略.

  • 参数名称缩写
let names = ["AT", "AE", "D", "S", "BE"]

var reversed = names.sorted(by: >)
print(reversed)

尾随闭包

info

尾随闭包是一个书写在函数括号之后的闭包表达式,函数支持将其作为最后一个参数调用。

func someFunctionThatTakesAClosure(closure: () -> Void) {
// 函数体部分
}

// 以下是不使用尾随闭包进行函数调用
someFunctionThatTakesAClosure({
// 闭包主体部分
})

// 以下是使用尾随闭包进行函数调用
someFunctionThatTakesAClosure() {
// 闭包主体部分
}

实例:

let names = ["AT", "AE", "D", "S", "BE"]

//尾随闭包
var reversed = names.sorted() { $0 > $1 }
print(reversed)

上述例子中的{ $0 > $1 }即是尾随闭包。

note

如果函数只需要闭包表达式一个参数,当使用尾随闭包时,甚至可以把()省略掉。

reversed = names.sorted { $0 > $1 }

函数作为参数

func generateNumber() -> Int {
Int.random(in: 1...20)
}

let newRolls = makeArray(size: 50, using: generateNumber)
print(newRolls)

多个函数作为参数

func doImportantWork(first: () -> Void, second: () -> Void, third: () -> Void) {
print("About to start first work")
first()
print("About to start second work")
second()
print("About to start third work")
third()
print("Done!")
}

使用闭包简化

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

捕获值

note

这个概念其实和javascript中的闭包作用域中[[Environment]]的概念很相似,都是能够在定义对应常量和变量的原域已经不存在的时候,闭包仍然可以在闭包函数体内引用和修改这些值。

func makeIncrementor(forIncrement amount: Int) -> () -> Int {
var runningTotal = 0
func incrementor() -> Int {
runningTotal += amount
return runningTotal
}
return incrementor
}

let incrementByTen = makeIncrementor(forIncrement: 10)

// 返回的值为10
print(incrementByTen())

// 返回的值为20
print(incrementByTen())

// 返回的值为30
print(incrementByTen())

以上的输出结果:

10
20
30

闭包是引用类型

func makeIncrementor(forIncrement amount: Int) -> () -> Int {
var runningTotal = 0
func incrementor() -> Int {
runningTotal += amount
return runningTotal
}
return incrementor
}

let incrementByTen = makeIncrementor(forIncrement: 10)

// 返回的值为10
incrementByTen()

// 返回的值为20
incrementByTen()

// 返回的值为30
incrementByTen()

// 返回的值为40
incrementByTen()

let alsoIncrementByTen = incrementByTen

// 返回的值也为50
print(alsoIncrementByTen())

上述程序输出的结果为:

50