Closures in swift are similar to building blocks,And can be called anywhere,It's like functions built into the c and objective c languages. Constant and variable references defined inside functions can be captured and stored in closures.Functions are considered special cases of closure,It comes in 3 forms.

Closed expression in swift language,Optimized as follows,Lightweight syntax style,These include:

Derive the type of the parameter and return the value from the context menu Recessive return from a single expression Abbreviated parameter name Tail closure syntax


Here is a general syntax definition for closures,It accepts parameters and returns the type of data:

{(parameters)->return type in

Here is a simple example:

let studname={println ("welcome to swift closures")}
studname ()

When we run the above program using playground,We get the following results

welcome to swift closures

The following closure accepts two parameters and returns a Boolean value:

{(int, int)->bool in
 statement 2
 statement n

Here is a simple example:

let divide={(val1:int, val2:int)->int in
 return val1/val2
let result=divide (200, 20)
println (result)

When we run the above program using playground,We get the following results


Expressions in closuresA convenient way of naming code blocks is through nested functions.Instead, the entire function declaration and name construct are used to represent the function.The syntax of the function is clear,The short statement is achieved through a closed expression.

Ascending orderThe sort string is a reserved function "sorted" in swift, which is an implementation provided in the standard library.The function sorts the given string in ascending order and returns the same size,And the elements of a new array of the same data type in the old array.The old array remains unchanged.

The ordering of the two parameters is represented inside the function:

Values ​​of known types are represented as arrays

The contents of the array (int, int), and returns a boolean (bool). If the array is not well sorted, it returns true, otherwise it returns false.

Ordinary functions are written with input strings,And pass it to the sort function to get the characters into the new array,As shown below:

func ascend (s1:string, s2:string)->bool {
 return s1>s2
let stringcmp=ascend ("swift", "great")
println (stringcmp)

When we run the above program using playground,We get the following results

The initial array sorting is given as "swift" and "great". The function used to sort the array is declared as a string data type,And the return type is Boolean. Compare two strings,And sorted in ascending order,And stored in the new array.If the sort is performed successfully,This function will return true;otherwise it will return false.

Closure expression syntax usage

Constant parameters:

Variadic and inout parameters

Closure expressions do not support default values.Variadic parameters and parameter tuples can also be used as parameter types and return types.

let sum=((no1:int, no2:int)->int in
 return no1 + no2
let digits=sum (10, 20)
println (digits)

When we run the above program using playground,We get the following results


Parameter and return type declarations mentioned in function declarations,It can also be represented by an inline closure expression function using the "in" keyword. Once the parameters and their return type "in" keywords are declared, they are used to represent the closure body.

Single expression implicit returnHere, the function type of the second parameter of the ranking function clearly states,A Boolean value must be returned by the closure.Because the closure body contains an expression (s1>s2) that returns a Boolean value, No ambiguity,The return keyword can be omitted.

To return an expression statement in a closure, The "return" keyword is omitted in its declaration section.

let count=[5, 10, -6, 75, 20]
var descending=sorted (count, {n1, n2 in n1>n2})
var ascending=sorted (count, {n1, n2 in n1<n2})
println (descending)
println (ascending)

When we run the above program using playground,We get the following results

[75, 20, 10, 5, -6]
[-6, 5, 10, 20, 75]

The statement itself clearly states thatReturns true when string1 is greater than string2, otherwise it is false, so the return statement is omitted.

Known types of closuresConsider adding two numbers.We know that the addition will return the integer data type.Therefore, closure declarations of known types

let sub=((no1:int, no2:int)->int in
 return no1-no2
let digits=sub (10, 20)
println (digits)

When we run the above program using playground,We get the following results


Declare short parameter names as closuresswift automatically provides shorthand parameter names for inline closures, You can use names from $0, $1, $2, etc.Refers to a closed parameter value.

var shorthand:(string, string)->string
println (shorthand ("100", "200"))

Here, $0 and $1 refer to the first and second string arguments of the closure.

When we run the above program using playground,We get the following results


swift makes it easy for users to indicate inline closures as abbreviated parameter names:$0, $1, $2 --- $n.

The definition part of the closure parameter list is omitted,Shorthand parameter names when we represent internal closure expressions. Abbreviated parameter names according to function type will be exported.The "in" keyword defined by the abbreviated parameter expression is omitted.

Closures as operation functionsswift provides an easy way to access members,Just provide the operator function as a closure. In the previous example the keyword "bool" was used to compare two strings,Returns "true" if equal, otherwise returns "false".

Expressions become simpler even in closures when manipulating functions:

let numb=[98, -20, -30, 42, 18, 35]
var sortednumbers=numb.sorted ({
 (left:int, right:int)->bool in
 return left<right
let asc=numb.sorted (<)
println (asc)

When we run the above program using playground,We get the following results

[-30, -20, 18, 35, 42, 98]

Closures as trailing packagesPass the last parameter of this function to the closing expression using a "trailing closure" declaration. It is written outside the function () using {}. When it cannot write a function inline on a line,Use it is needed.

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

Where {$0>$1} represents a trailing closure as an external (name) declaration.

import foundation
var letters=["north", "east", "west", "south"]
let twoletters=letters.map ({(state:string)->string in
 return state.substringtoindex (advance (state.startindex, 2)). uppercasestring
let stletters=letters.map () {$0.substringtoindex (advance ($0.startindex, 2)). uppercasestring}
println (stletters)

When we run the above program using playground,We get the following results

[no, ea, we, so]

Capturing values ​​and reference typesWith the help of closures, swift finishes capturing the values ​​of constants and variables.It also references modified values,Even constants and variables no longer exist in the closure body.

Capturing constant and variable values ​​is done by writing functions using nested functions,This is achieved using other function bodies:

A nested function capture External function parameters Capturing variables defined in constants and external functions

When a constant or variable is declared in a function in swift,References to variables are also automatically created by closure.It also provides tools to reference more than two variables as the same closure as follows:

let decrem=calcdecrement (fordecrement:18)
decrem ()

Here, both onedecrement and decrementing variables point to the same memory block closed reference.

func calcdecrement (fordecrement total:int)->()->int {
 var overalldecrement=100
 func decrementer ()->int {
 overalldecrement-= total
 println (overalldecrement)
 return overalldecrement
 return decrementer
let decrem=calcdecrement (fordecrement:18)
decrem ()
decrem ()
decrem ()

When we run the above program using playground,We get the following results:


When each external function calcdecrement is called, the decrementer () function is called and decremented by the value 18, and the result is returned with the help of the external function calcdecrement.Here, calcdecrement acts as a closure.

Even if the function decrement () takes no parameters,Closing by default means "overall decrementing" of the variable "total" by getting its value.A copy of the value for the specified variable is stored using the new decrementer () function.swift allocates and frees memory space by handling memory management functions when variables are not in use.

Here is a wave of summary ~

/* Closures
* Closures are self-contained blocks of functional code,Can be used in code or used as a parameter.
* Closures in swift are similar to blocks in c, oc, and lambdas in other programming languages ​​such as python.
* Closures can capture and store references to any constants and variables defined in the context.
This is the so-called variable and self-closing of variables,* So named "closures". Swift also handles memory management of all captured references.
* Global functions and nested functions are actually special closures.
* The form of closure is:
* (1) global functions are closures,Has a name but cannot capture any value.
* (2) Nested functions are closures,And have a name,Capturing values ​​within closed functions is also possible.
* (3) Closure expressions are all unnamed closures.
Using lightweight syntax,You can capture values ​​based on context.
* Closures in swift have many optimizations:
* (1) Infer parameters and return value types based on context
* (2) Implicit return from a single-line expression closure (that is, the closure body has only one line of code,You can omit return)
* (3) can use simplified parameter names,Such as $0, $1 (starting from 0, indicating the i-th parameter ...)
* (4) Trailing closure syntax is provided
* /
//The following uses the sort method in the Swift standard library to simplify the closure step by step.
//sort function requires two parameters
//Parameter one:array
//Parameter two:a closure:with two parameters,These two parameter types are the same as the element types in the array,The return value is bool
var names=["swift", "arial", "soga", "donary"]
//The first way:use functions
func backwards (firststring:string, secondstring:string)->bool {
 return firststring>secondstring //sort in ascending order
//here the second parameter,Passed a function
//reversed is equal to ["swift", "soga", "donary", "arial"]
var reversed=sort (nams, backwards)
//The second way:using closures
//The complete closure is written with a parameter list and return value in curly braces,Use the keyword in to indicate the beginning of the closure body
//(firststring:string, secondstring:string) closure parameter list
//->bool indicates that the closure return value type is bool
//in keyword indicates the start of the closure body
reversed=sort (names, {(firststring:string, secondstring:string)->bool in
 return firststring>secondstring
//You can further simplify the writing here,Because closure code is relatively short,Can be written on one line
reversed=sort (names, {(firststring:string, secondstring:string)->bool in return firststring>secondstring})
//Let's simplify it further:automatically infer the type based on the environment context
//the parameter list does not specify the type,There is no indication of the return type,This is because swift can infer from the context
//the type of firststring and secondstring will be the type of the names array element,The return value type will be obtained according to the result of the return statement.
reversed=sort (names, {firststring, secondstring in return firststring>secondstring})
//Simplify further:implicit return (single-line statement closure)
//Because the closure body has only one line of code,You can omit return
reversed=sort (names, {firststring, secondstring in firststring>secondstring})
//Simplify further:use simplified parameter names ($i, i=0,1,2 ... starting from 0)
//swift will infer that the closure requires two parameters,The same type as the names array element
reversed=sort (names, {$0>$1})
//The simplest way to write:use operators
reversed=sort (names,>)
* Trailing closures
* If the function requires a closure parameter as a parameter,And this parameter is the last parameter,And this closure expression is very long,* Using trailing closures is useful.
Trailing closures can be placed outside function parameter lists,That is outside the parentheses.
If the function has only one parameter,* Then you can omit the parentheses () and follow the closure directly.
* /
//array method map () requires a closure as a parameter
let strings=numbers.map {//() after the map function can be omitted
 (var number)->string in
 var output=""
 while number>0 {
 output=string (number%10) + output
number/= 10
 return output
/* Capture value
* Closures can capture defined constants and variables based on the context of the environment.
Closures can reference and modify these captured constants and variables,* Even if it is defined as a constant or variable in the original range, it no longer exists (very powerful).
* The simplest form of closure in swift is a nested function.
* /
func increment (#amount:int)->(()->int) {
 var total=0
 func incrementamount ()->int {
 total +=amount //total is a variable inside the external function body,Can be captured here
return total
 return incrementamount //returns a nested function (closed)
//closures are reference types,So incrementbyten declared as a constant can also modify the total
let incrementbyten=increment (amount:10)
incrementbyten () //return 10, incrementbyten is a closure
//Here is no change to the reference to increment, so the previous value will be saved
incrementbyten () //return 20
incrementbyten () //return 30
let incrementbyone=increment (amount:1)
incrementbyone () //return 1
incrementbyone () //return 2
incrementbyten () //return 40
incrementbyone () //return 3
  • Previous JavaScript to write, read, and delete cookies
  • Next JS achieve slide text box zoom stretch effect code