Mom doesn't have to worry about my closures anymore.
注:本文为作者自己总结,过于基础的就不再赘述 ,都是亲自测试的结果。如有错误或者遗漏的地方,欢迎指正,一起学习。
The closure in Swift is a very powerful thing, and closures are self-contained blocks of function code that can be passed and used in code. Similar to code blocks (blocks) in C and Objective-c. We must master this! Must master! Must master!重要的事情要说三遍
Closures can capture and store references to any constants and variables in the context in which they are located. This is called closed merge wrapped with these constants and variables, commonly known as closures. Let's conquer it!
1. Closure function
The official is generally using a sort method when explaining the closure function sort()
, let's take a look at this example:
let names = ["Chris""Alex""Ewa""Barry""Daniella"]func backwards(s1: String, s2: String) -> Bool { return s1 > s2}
Here we define an String
array of types, then define a function
, accept two String
parameters that receive two types, return bool
And then we're going to get a look at the sort()
rules that we're going to sort this array by the way we define it, var reversed = names.sort(backwards)
This sort()
joins the array in Swift 2.0, and the member method that becomes the array can be called directly, passing in the same two values as the array type, and returning bool
, if true, putting the first argument in front of the second (that is, descending), whereas you know
So, what we mean by this function is that if the first one returns True (S1>S2) than the second argument, it's a descending arrangement, and here's the result: [Ewa, Daniella, Chris, Barry, Alex]
People look at the official sort()
also do not see the specific implementation, so this piece may not be very clear, then we write a sort ourselves, also passed our function.
Func Mysort (vararr:[String], Sortstr: (String,String)->bool)->[String]{if(Arr.count = =0){returnArr } LetCount = Arr.countvartemp ="" forIinch 0.. <count { forJinchi+1.. <count {if(!sortstr (Arr[i],arr[j])) {temp = Arr[i] arr[i] = arr[j] arr[j] = temp}} }returnarr;}
is actually a simple bubble sort, just handing the rules to the caller.
The calling method mySort(names, sortStr: backwards)
is passed in an array and a function type. Get the result: [Ewa, Daniella, Chris, Barry, Alex]
the same as the official sort.
In the following example, we use our own sort, the code is here. You can see it all clearly.
A knowledge point needs to be added here.
区间运算 :0...n 表示0-n的闭合区间 0..<n 表示一个包含0 不包含n半开半闭
2. Closed-Packet expression syntax
However, this is a rather lengthy way of essentially writing a single-expression function (a > B), but do we also write a function? Of course not, we can construct an inline sort closure with the closed-expression syntax.
(parameters) ->in statements}
The closure expression syntax can use constants, variables, and inout types as parameters, and does not provide a default value. You can also use variable parameters at the end of the parameter list. Tuples can also be used as parameters and return values.
let arr1 = mySort( (names) , sortStr: { (s1:String,s2:String) -> Bool in return s1>s2})
Here we put the above into the function where we passed in a closure. There is not much explanation here. Exactly according to the syntax type above
- Infer types based on context
Because the mySort
second parameter we write is a function of type (string, String)--bool, so actually string,string and bool types do not need to be part of the definition of a closure expression. Because all types can be inferred correctly, the return arrows (-a) and the parentheses around the parameters can also be omitted:
So we can write this:
letinreturn s1>s2 })
See, smart Swift helps us shorten closures a lot.
- Single-expression closed Baoyin return
A single-line expression closure can implicitly return the result of a single-line expression by hiding the return keyword, where we are a single-line expression.
注:不要方便的用惯了多行表达式别也给省略了
letin s1>s2 })
Our code is a lot shorter.
- Parameter name abbreviation
Swift automatically provides the parameter name abbreviation function for inline functions, which you can directly 1,$2 to sequentially invoke the parameters of the closure. If you use a parameter name abbreviation in a closure expression, you can omit the definition of it in the closure parameter list, and the type that corresponds to the abbreviation for the parameter name is inferred from the function type. The In keyword can also be omitted
This is when our closures become the following.
let$0>$1 })
Wow! Too strong, Swift is too powerful, you think this is the ultimate goal, wrong and more serious
The string type of Swift defines the implementation of strings for the greater-than sign (>), which takes two arguments of type string as a function and returns a value of type bool
You can simply pass a greater-than sign, and Swift can automatically infer that you want to implement the string function with the greater-than sign
In the end, our closures turned out like this.
let//[Ewa, Daniella, Chris, Barry, Alex]
A trailing closure is a closure expression that is written after the function brackets, and the function supports calling it as the last argument.
let$0>$1 }
Trailing closures are useful when closures are so long that they cannot be written on a single line. This is the way we often do.
3. Capture value
Closures can capture constants or variables in the context in which they are defined. Even though the original domain that defines these constants and variables does not already exist, closures can still reference and modify these values in the closure function body.
See this paragraph is not very faint ah, haha we look at an example you understand.
func makerunstep (step:int) -> () -> int{var total = 0 ; // func run () Int {// total+=step; return total; //} return { () -> Int in Total+=step; return total; }}
这里我们定义了一个函数,传入一个`Int` ,返回`()->Int`的函数类型 。在函数中我们定义一个统计总数的变量`total` ,直接返回一个闭包 ,在闭包中使用传入的参数和变量`total` ,我们这里也可以用我注释的那段,写一个内嵌函数 ,然后返回这个内嵌函数 。
let ten = makeRunStep(10);
Here, pass in a 10 and assign the returned function type to a constant ten.
Execute the method to ten()
get the result 10
When we go back to execution ten()
, because the step is not modified, total actually captures and stores a copy of the variable, and the copy is stored in ten with the closure, because the value of total is modified every time the function is called. Instead of just copying the initial value of the variable, the closure captures a reference to the current total variable. Capturing a reference guarantees that total can continue to increase when the makerunstep ends and does not disappear, and the next time that the closure is executed
So the result is: 20
let ten = makeRunStep(10);ten() //10ten() //20ten() //30ten() //40let ten2 = makeRunStep(10//10
Restart count if called again makeRunStep(7)
let seven = makeRunStep(7//7//14//21//28
You see these groups of data probably understand what the meaning of it, in fact, the real reason is that the closure is a reference type, let ten = makeRunStep(10);
although we here with a constant to receive the closure, but directly accept its reference, not the closure itself.
let ten = makeRunStep(10);ten() //10ten() //20ten() //30ten() //40let//50//60
Two different constants can refer to a closure at the same time.
About closures are roughly that much. If you have any questions, you can learn from each other. Hope to make progress together!
Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.
Swift's explanation of the four-------mom doesn't have to worry about my closures anymore.