Latest web development tutorials

Swift closure

Closures (Closures) is a functional self-contained block of code, you can use or be used as a parameter value in the code.

Swift closures in C and Objective-C code blocks (blocks) and some other programming languages ​​anonymous function is quite similar.

Global functions and nested functions is actually a special closure.

Closure of the form:

Global Functions Nested functions Expression closures
I have a name but can not capture any value. It has a name, but also to capture value within the function closed. Nameless closure, use lightweight syntax, you can capture the value based on the context.

Swift closures have a lot of optimization places:

  1. Depending on the context infer parameter and return value type
  2. From single-line expression closure implicit return (that is, the closure body is only one line of code, you can omit return)
  3. It can be used to simplify the parameter name, such as $ 0, $ 1 (from 0, indicating that the i-th argument ...)
  4. Providing trailing closure syntax (Trailing closure syntax)
  5. grammar

    The following defines a receiving parameter and returns the specified type of closure syntax:

    {(parameters) -> return type in
       statements
    }
    

    Examples

    import Cocoa
    
    let studname = { print("Swift 闭包实例。") }
    studname()
    

    The above program execution output is:

    Swift 闭包实例。
    

    The following closures form takes two parameters and returns a Boolean value:

    {(Int, Int) -> Bool in
       Statement1
       Statement 2
        ---
       Statement n
    }
    

    Examples

    import Cocoa
    
    let divide = {(val1: Int, val2: Int) -> Int in 
       return val1 / val2 
    }
    let result = divide(200, 20)
    print (result)
    

    The above program execution output is:

    10
    

    Expression closures

    Closures expression is a way to build the use of simple syntax inline closures. Closures expression syntax provides some optimization so that compose the closure becomes simple and clear.


    sort function

    Swift standard library provides a function named sort, it will be sorted according to the closure function you provide will be used to sort the known type values ​​in the array.

    After the completion of the sort, sort (_ :) method returns an array of the same size as the original, the new array contains the same type of element and the element has been properly sorted, the original array is not modified sort (_ :) methods.

    sort (_ :) method takes two arguments:

    • An array of known type
    • Closure function, that function closures need to pass an array of elements with the same type of two values ​​and returns a Boolean value to indicate that the first parameter after the end of the sorting incoming row in front of or behind the second parameter. If the first parameter values appear in front of the second parameter values, sort the closure function needs to return true , contrary to return false .

    Examples

    import Cocoa
    
    let names = ["AT", "AE", "D", "S", "BE"]
    
    // 使用普通函数(或内嵌函数)提供排序功能,闭包函数类型需为(String, String) -> Bool。
    func backwards(s1: String, s2: String) -> Bool {
        return s1 > s2
    }
    var reversed = names.sort(backwards)
    
    print(reversed)
    

    The above program execution output is:

    ["S", "D", "BE", "AT", "AE"]
    

    If the first character string (s1) is greater than the second string (s2), backwards function returns true, indicating that the new array should appear before s1 s2. For the characters in the string, the "greater than" means "later appear in alphabetical order." This means that the letter "B" is greater than the letter "A", the string "S" is greater than the string "D". It will reverse alphabetical sort, "AT" will be sorted before "AE".


    Parameter name abbreviation

    Swift automatically provides an inline function parameter name abbreviation, you can directly through the $ 0 parameter closures of $ 1, $ 2 to call order.

    Examples

    import Cocoa
    
    let names = ["AT", "AE", "D", "S", "BE"]
    
    var reversed = names.sort( { $0 > $1 } )
    print(reversed)
    

    $ 0 and $ 1 for the closure of the first and the second parameter of type String.

    The above program execution output is:

    ["S", "D", "BE", "AT", "AE"]
    

    If you use the parameter name abbreviation in the closure expression, you can closure parameter list its definition is omitted, and the corresponding parameter name Acronym types will be inferred by function type. in keywords it can also be omitted.


    Operator function

    In fact there is a shorter way to write the above example closures expression.

    Swift's String type defines on greater-than sign ( > string) implementation, as a function that takes two String type parameter and returns a Bool value type. This coincided with the sort(_:) type function of the second parameter of the method needs to conform. Therefore, you can simply pass a greater-than sign, Swift can automatically infer that you want to use is greater than the number of string functions to achieve:

    import Cocoa
    
    let names = ["AT", "AE", "D", "S", "BE"]
    
    var reversed = names.sort(>)
    print(reversed)
    

    The above program execution output is:

    ["S", "D", "BE", "AT", "AE"]
    

    Trailing Closures

    Trailing closure is a function written in parentheses after the closure of expressions, functions to support its call as the last parameter.

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

    Examples

    import Cocoa
    
    let names = ["AT", "AE", "D", "S", "BE"]
    
    //尾随闭包
    var reversed = names.sort() { $0 > $1 }
    print(reversed)
    

    sort () after {$ 0> $ 1} trailing closure.

    The above program execution output is:

    ["S", "D", "BE", "AT", "AE"]
    

    Note: If the function only one parameter expression closures, when you use trailing closures, you can even put () omitted.

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

    Captured value

    Closures can be constant or variable capture in the context of its definition.

    Even the definition of these constants and variables of the original domain does not exist, the closure can still function in vivo closure referencing and modification of these values.

    Swift easiest form of closure is nested function, the function is defined in the body of the other functions of the function.

    The nested function can capture all of its external function parameters and defined constants and variables.

    Look at this example:

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

    A function makeIncrementor, it has a parameter of type Int amout, and it has an external parameter name forIncremet, means that when you call, you must use the external name. The return value is a ()-> Int function.

    In the title function, declare a variable and a function runningTotal incrementor.

    incrementor function does not get any arguments, but in the body of the function to access the runningTotal and amount variables. This is because it contains the body of the function by capturing its existing runningTotal and variable amount realized.

    Since there is no modification amount variable, incrementor actually capture and store a copy of the variable, which is stored together with a copy as incrementor.

    So when we call this function will accumulate:

    import Cocoa
    
    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())
    

    The above program execution output is:

    10
    20
    30
    

    Closures are reference types

    The above example, incrementByTen is constant, but the point of closure of these constants can still increase the value of its variable capture.

    This is because the functions and closures are reference types.

    Whether you are a function / closure assigned to a constant or variable, you are actually setting the value of the constant / variable corresponding function / closure references. The above example, incrementByTen closures reference point is a constant, rather than the content of the closure itself.

    This also means that if you assign the closure of the two different constants / variables, both values ​​will point to the same closure:

    import Cocoa
    
    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())
    

    The above program execution output is:

    50