Closure Expressions
The Sorted Method
let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
func backward(_ s1: String, _ s2: String) -> Bool {
return s1 > s2
}
var reversedNames = names.sorted(by: backward)
// reversedNames is equal to ["Ewa", "Daniella", "Chris", "Barry", "Alex"]
the above example shows that we use a backward
function as a value to be sent into the sorted
function.
but this is written as a closure ordinarily.
reversedNames = names.sorted(by: { (s1: String, s2: String) -> Bool in
return s1 > s2
})
We can see the closures structure:
{
(parameters)
->return type
in
statements
}
Inferring Type From Context
At the above example, the sorted
function always be called on a strings array, so its argument must be a function of type (String, String) -> Bool
, so we don't need to written the whole form.
It can be written as below:
reversedNames = names.sorted(by: { s1, s2 in return s1 > s2 } )
Implicit Returns from Single-Expression Closures
And if there only be a single expression in closures, we can omit the return
as well.
reversedNames = names.sorted(by: { s1, s2 in s1 > s2 } )
Shorthand Argument Names
Simpler and simpler, as below:
reversedNames = names.sorted(by: { $0 > $1 } )
Operator Methods
Simplest!!!
reversedNames = names.sorted(by: > }
This >
can be related to a function, actually, it dose a function.
Capturing Values
Warning!!!
Watch out this expression!
func makeIncrementer(forIncrement amount: Int) -> () -> Int {
var runningTotal = 0
func incrementer() -> Int {
runningTotal += amount
return runningTotal
}
return incrementer
}
let incrementByTen = makeIncrementer(forIncrement: 10)
incrementByTen()
// returns a value of 10
incrementByTen()
// returns a value of 20
incrementByTen()
// returns a value of 30
let incrementBySeven = makeIncrementer(forIncrement: 7)
incrementBySeven()
// returns a value of 7
We can see the above example, due to the nested function incrementer
capture the runningTotal
, so runningTotal
will remains even if incrementByTen
finish, and incrementBySeven
is not influenced.
Because the function type and closures type is reference types.
Same for closures, but it will may cause strong reference cycles, which we will learn how to solve.
Escaping Closures
If we need the closures excute after the function ends, we should use key word @escaping
before the parameter’s type.
var completionHandlers: [() -> Void] = []
func someFunctionWithEscapingClosure(completionHandler: @escaping () -> Void) {
completionHandlers.append(completionHandler)
}
Let’s think!
网友评论