Swift Learning Note Nine

Source: Internet
Author: User

Closed Package

Closures are blocks of self-contained (self-contained) that can be used and passed in code.

Closures in Swift are similar to the blocks in C and OC. They can capture and store references to any constants and variables in the context in which they are defined. Swift handles captured memory management without the need for developer action.

The global functions and nested functions described earlier are in fact a special case of closures, with the following three types of closures:

1. A global function is a closure that has a name and does not capture any value

2. A nested function is a closure that has a name and is capable of capturing values from within the function that contains it

3. A closure expression is a closure that is written in lightweight syntax without a name to capture the value from the context that contains it

Swift's closure expression style is very concise and clear, and has done a lot of optimizations to encourage the use of simple and free syntax in general, optimized as follows:

Detecting parameters and return value types from the context

Single-statement closed Baoyin return

Abbreviated parameter name

Post-closing packet syntax

Closed-Packet expression

A nested function is a good representation of a named block of code contained in a word that is part of a larger function. However, it may sometimes be necessary to use a simpler form, such as a construct without a name and all declarations. This is especially noticeable when you are manipulating functions that receive other functions as arguments.

A closure expression provides a concise and unambiguous syntax for writing inline closures. The closure expression provides a lot of syntax optimizations to make the shorthand closure less ambiguous.

The following example demonstrates this optimization of a closure expression by continually refining a simple sorted method in an increasingly concise manner.

The sorted method is a method provided by the standard library of Swift, which arranges the elements of an array of known types according to a closure package that you provide. It takes two parameters, the first is an array of known types, the other is a closure, the closure accepts two parameters of the same type, and returns a Boolean value to determine whether the first argument should precede the second.

Assuming that an array is of type String, then the second parameter of the sorted function should be closed (string,string), the BOOL function type.

Let names = ["Chris""Alex" "Ewa " " Barry " " Daniella "]

The first way to provide a sort closure is to write a function of the correct type, and then pass the function as the second argument to the sorted function:

Func Backwards (s1:string, s2:string), Bool {    return s1 >= sorted (names, back Wards)//  reversed are equal to ["Ewa", "Daniella", "Chris", "Barry", "Alex"]

Of course, this approach is cumbersome, in this case, it is recommended to use the closure expression syntax to write a more concise inline sorting closure.

The general form of a closure expression is:

{(parametersreturn typein    statements}

The closure expression syntax can use variable arguments, constant parameters, and inout parameters. However, you cannot provide default values for parameters. You can specify a name for a mutable parameter at the end of the parameter list to use a mutable parameter. Tuples can be used as parameter types and return value types.

The following is the closure expression version of the sort closure in the previous example:

inch    return s1 > s2})

Note that there is a difference between the type of the parameter and the return value in the previous example, because it is written in curly braces rather than outside.

Here the In keyword is used to separate the two parts, indicating that the parameter and the return value type have been defined, followed by the closure part. Here in the back of the line is not necessary, for example, the closure of the body is very short, you can write only one line:

inch return s1 > s2})

Infer a type from the context

Because a sort closure is passed as a parameter to a function, Swift can infer its parameter type and the type of the value it returns from the type of the second parameter of the sorted function. This parameter expects a (string, string)-type bool function, which means that (string, string) and bool do not need to be written in the definition of the closure expression. So the more concise version is as follows:

inch return s1 > s2})

When a closure is passed to a function in the form of a closure expression, its parameter type and return value type can always be inferred. Therefore, when a closure is used as a parameter to a function, it is not necessary to write out its full form. Of course, it is recommended to write the complete form when the shorthand form will cause ambiguity.

Implicit return of a single-statement closure

A single statement closure can omit the return keyword and return the result implicitly, so it can be further simplified to:

 in S1 > s2})

Abbreviated parameter name

Swift automatically gives the inline closure a shorthand form of the parameter name, by $0,$1,$2 ... to refer to the first ... parameters. Therefore, the sort closure can be abbreviated as:

Reversed = sorted (names, {$0 > $1 })

Here, $ and $ are the first and second string.

operator functions

The closure expression in the example above can also be more concise, and Swift's string type defines the implementation of the string version of "greater Than operator (>)". This implementation is a function that accepts two string type arguments and returns a Boolean type. This satisfies the function type required by the second argument of the sorted function. So, you can just pass the "greater than operator" in, and Swift will infer that you are implementing a string version of it that you want to use:

Reversed = sorted (names, >)

Rear Closure Package

If you want to pass a closure expression as the last argument to a function, and the closure form is very long, it is more appropriate to write the code in a closed-down manner. A post-closure is a closure expression that is written behind the parentheses of the function calls it supports. Like what:

Func somefunctionthattakesaclosure (Closure: () )    {//  function body goes here  // Here's how to call the This function without using a trailing closure:  Somefunctionthattake Saclosure ({    //  closure ' s body goeshere/ Here's how to call This function with a trailing closure instead:  somefunctionthattakesaclosure () {    // trailing closure ' s body goeshere}

Therefore, the sort closures can be further abbreviated as:

Reversed = sorted (names) {$0 > $1 }

Note: If the closure expression is a unique parameter of a function and is written in a post-syntax, you can omit the parentheses following the function name.

When the closure expression is particularly long, the post-closure is particularly useful. For example, the SWIFT array has a map (_:) method that takes a closure expression as its only parameter, which is run once on each element of the array, returns a new element corresponding to the element, the implementation of the Map method, and the return value type are left to the closure to decide. Use the Map (_:) method, in the following example, the array [16, 58, 510] is used to create a new array ["Onesix", "Fiveeight", "Fiveonezero"].

Let Digitnames = [    0:"Zero",1:" One",2:" Both",3:"three",4:" Four",    5:"Five",6:"Six",7:"Seven",8:"Eight",9:"Nine"]let Numbers= [ -, -,510]let Strings=Numbers.map {(var number)-Stringinchvar output=""     whileNumber >0{Output= Digitnames[number%Ten]! +Output Number/=Ten    }    returnOutput}//Strings is inferred to be of type [String]//Its value is ["Onesix", "Fiveeight", "Fiveonezero"]

Note that the parentheses are omitted from the map, because the closure expression is passed in as a unique parameter, and in the argument list of the closure, a variable argument is used so that the local variable number is not created in the enclosing body and the parameter value is assigned to it.

One more thing to note here is the Digitnames[number% 10]! Here the exclamation point, described earlier, the dictionary of the next banner return is an optional type (Optional type), where the context is determined that this value must exist, so use an exclamation point to force the expansion of this optional type.

Capturing values

A closure can capture variables or constants from the context in which it is defined. Closures can then be used to reference or change these constants or variables in their own bodies, even when the original scope of the variables and constants that define them is no longer present. The simplest example is a nested function in which functions defined inside a function can capture variables and constants inside an external function, and if the function is returned, it allows you to refer to and manipulate the constants and variables, even though the external function has been returned and does not exist. Like what:

Func makeincrementer (forincrement amount:int), int {    0    , int {         + =        amountreturn  runningtotal    }     return  Incrementer}

Here Incrementer is returned by the outer function, allowing to get and manipulate runningtotal and amount, which in fact captures the runningtotal reference instead of the value copy, so that each time it is called, the same variable is changed. And amount is not changed, so it is captured in the form of a value copy.

Swift automatically determines which variables need to capture the reference, which captures the value copy, and all memory management is automatically managed by swift, without the need for manual management by the developer.

Note: If you assign a closure to a property of a class instance, and the closure refers to itself by referencing that instance or its members, then a strong reference loop is formed between the closure and the class instance. Swift uses a reference list to break this strong reference loop, which is described later.

Closures are reference types

When a closure is assigned to a constant, the variables it captures can still be changed by the closure, because the function and the closure are reference types, and at the time of assignment, only their reference addresses are assigned to the variable, not its internal code block. For example, if you assign a closure to two constants, these two constants actually point to the same closure.

Swift Learning Note Nine

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.