## Closures
Global and nested functions, as introduced in Functions, are actually special cases of closures. Closures take one of three forms:
* Global functions are closures that have a name and do not capture any values.
* Nested functions are closures that have a name and can capture values from their enclosing function.
* Closure expressions are unnamed closures written in a lightweight syntax that can capture values from their surrounding context.
Closure expression syntax has the following general form:
~~~
{ (parameters) -> return type in
statements
}
~~~
~~~
let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella”]
func backwards(s1: String, s2: String) -> Bool {
return s1 > s2
}
// 方法1
var reversed = sort(names, backwards)
// reversed is equal to ["Ewa", "Daniella", "Chris", "Barry", "Alex”]
// 1.5
reversed = sort(names, { (s1: String, s2: String) -> Bool in return s1 > s2 } )
// 方法2
reversed = sort(names, { s1, s2 in return s1 > s2 } )
// 方法3
reversed = sort(names, { s1, s2 in s1 > s2 } ) // Implicit Returns from Single-Expression Closures
// 方法4
reversed = sort(names, { $0 > $1 } )
// 方法5
reversed = sort(names, >)
// 方法6
reversed = sort(names) { $0 > $1 }
~~~
It is always possible to infer parameter types and return type when passing a closure to a function as an inline closure expression. As a result, you rarely need to write an inline closure in its fullest form.
~~~
func someFunctionThatTakesAClosure(closure: () -> ()) {
// function body goes here
}
// here's how you call this function without using a trailing closure:
someFunctionThatTakesAClosure({
// closure's body goes here
})
// here's how you call this function with a trailing closure instead:
someFunctionThatTakesAClosure() {
// trailing closure's body goes here
}
~~~
If a closure expression is provided as the function’s only argument and you provide that expression as a trailing closure, you do not need to write a pair of parentheses () after the function’s name when you call the function.
~~~
let digitNames = [
0: "Zero", 1: "One", 2: "Two", 3: "Three", 4: "Four",
5: "Five", 6: "Six", 7: "Seven", 8: "Eight", 9: "Nine"
]
let numbers = [16, 58, 510]
let strings = numbers.map {
(var number) -> String in
var output = ""
while number > 0 {
output = digitNames[number % 10]! + output
number /= 10
}
return output
}
// strings is inferred to be of type String[]
// its value is ["OneSix", "FiveEight", "FiveOneZero"]
~~~
~~~
func makeIncrementor(forIncrement amount: Int) -> () -> Int {
var runningTotal = 0
func incrementor() -> Int {
runningTotal += amount
return runningTotal
}
return incrementor
}
let incrementByTen = makeIncrementor(forIncrement: 10)
incrementByTen()
// returns a value of 10
incrementByTen()
// returns a value of 20
incrementByTen()
// returns a value of 30
let incrementBySeven = makeIncrementor(forIncrement: 7)
incrementBySeven()
// returns a value of 7
incrementByTen()
// returns a value of 40
let alsoIncrementByTen = incrementByTen
alsoIncrementByTen()
// returns a value of 50
~~~
functions and closures are reference types.
- About Swift
- The Basics
- Basic Operators
- String and Characters
- Collection Types
- Control Flow
- Functions
- Closures
- Enumerations
- Classes and Structures
- Properties
- Methods
- Subscripts
- Inheritance
- Initialization
- Deinitialization
- Automatic Reference Counting
- Optional Chaining
- Type Casting
- Nested Types
- Extensions
- Protocols
- Generics
- Advanced Operators
- A Swift Tour