Swift Learning Notes

Closures

2021-08-02  本文已影响0人  宋奕Ekis

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 backwardfunction 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 sortedfunction 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!

上一篇 下一篇

猜你喜欢

热点阅读