Detail the use of functions and function closures in Swift

  • 2020-05-19 06:00:27
  • OfStack

1. The introduction

A function is a piece of code with a specific function that is called with a specific name. Swift provides 10 flexible ways to create and call functions. In fact, at Swift, each function has one type, which is determined by the parameters and return values. The big difference between Swift and Objective-C is that functions in Swift can be nested.

While closures in Swift are blocks of code with 1 specific function, the 10 categories are similar to the block syntax in Objective-C. The closure syntax style in Swift is 10 points concise and ACTS like a function.

2. Creation and call of functions

Functions are defined by function name, parameters and return value. Parameters and return value determine the type of a function. When a function is called, the function name is used to make the call.


// The incoming 1 A name   Print and return it 
func printName(name:String) -> String {
  print(name)
  return name
}
// Make a function call 
printName("HS")

You can also create functions without parameters:


func onePuseTwo()->Int {
  return 1+2
}
onePuseTwo()
 You can also create functions that do not return a value: 

func sayHello(){
  print("Hello")
}
sayHello()

The function types described above are common. For functions with multiple return values, Objective-C is difficult to deal with in 10 points. Developers usually adopt the collection method such as dictionary, array, or simply use block callback.


func tuples()->(Int,String){
  return (1,"1")
}
tuples()

It can also be a function that returns a value of type Optional, with support for returning nil, as shown below:


func func1(param:Int)->Int? {
  guard(param>0)else{
    return nil
  }
  return param
}
func1(0)
func1(1)

Before the parameter name of the function, the developer can also add another parameter name as the external parameter name. An example is as follows:


func func1(count param:Int ,count2 param2:Int)->Int? {
  // Still in use internally param
  guard(param>0)else{
    return nil
  }
  return param
}
// External call usage count
func1(count: 0,count2: 0)
func1(count: 1,count2: 1)

In fact, the parameter list in the Swift function has such a feature that, except for the first parameter, all subsequent parameters will be added with an external name with the same internal name by default. If the developer does not want to use this external name, use the _ symbol to set it. The example is as follows:


func func2(param:Int,param2:Int,param3:Int) {
  
}
// It has an external name 
func2(0, param2: 0, param3: 0)
func func3(param:Int,_ param2:Int,_ param3:Int) {
  
}
// No external name 
func3(0, 0, 0)

Swift also supports developers to create a default value for a function parameter. If a function parameter has a default value, the developer can omit this parameter when calling the function. An example is shown below:


func func4(param:Int=1,param2:Int=2,param3:Int) {
  print(param,param2,param3)
}
func4(3,param3:3)

Another case is also handled in Objective-C. For functions with variable number of parameters, Objective-C1 will generally use the list pointer as described in the previous section. It is 10 minutes easy to write such functions in Swift.


func func5(param:Int...) {
  for index in param {
    print(index)
  }
}
func5(1,2,3,4)

The parameter in Swift is a constant by default, and it is impossible to modify the value of the external incoming parameter in the function. If there is a requirement, it is necessary to declare the parameter as inout type. The example is as follows:


func func6(inout param:Int) {
  param = 10
}
var count = 1
// You're actually passing in the parameter address 
func6(&count)
print(count)

3. Function types

A function is a special data type, and each function belongs to one data type. An example is as follows:


func func7(a:Int,_ b:Int)->Int{
  return a+b
}
var addFunc:(Int,Int)->Int = func7
addFunc(1,2)

The function can also be passed in as a parameter to another function, which is similar to the block syntax in Objective-C, for example:


func onePuseTwo()->Int {
  return 1+2
}
onePuseTwo()
 You can also create functions that do not return a value: 

func sayHello(){
  print("Hello")
}
sayHello()

0

A personal function can also be used as the return value of another function, as shown below:


func onePuseTwo()->Int {
  return 1+2
}
onePuseTwo()
 You can also create functions that do not return a value: 

func sayHello(){
  print("Hello")
}
sayHello()

1

4. Look at closures from a system function

The Swift standard library provides an sort sorting function. For an array with an existing element type, the call to sort will reorder and return the new sorted array. The sort function can accept a closure of type Bool with a return value to determine whether the first element precedes the second. The code example is as follows:


func onePuseTwo()->Int {
  return 1+2
}
onePuseTwo()
 You can also create functions that do not return a value: 

func sayHello(){
  print("Hello")
}
sayHello()

2

Swift language has a very remarkable characteristic is concise, can infer the types of 1 from context, development of all types of writing can be omitted, that is a Swift language design train of thought, as a result of the closure is a function as a parameter to in the function, because of the type of function parameters are determined, thus the type of closure can be deduced from the compiler, developers can also be closure parameter types and return value is omitted, the above code can be abbreviated as follows:


// Omits both the parameter type and the return value of the closure 
array = array.sort({(p1,p2) in return p1>p2})

In fact, if the function body in the closure is only 1 line of code, you can omit the return keyword and implicitly return the value of this line of code, as follows:


func onePuseTwo()->Int {
  return 1+2
}
onePuseTwo()
 You can also create functions that do not return a value: 

func sayHello(){
  print("Hello")
}
sayHello()

4

It's a bit of a shock to see that the expression above can be reduced to this! However, you are still underestimating the Swift development team, and the following grammar rules will let you know what is the ultimate in simplicity. You can see that the above code implementation still has three parts: parameters and return values, closure keywords, and function bodies. The parameters and return values are the list of parameters, p1, p2, although the parameter types and return value types are omitted, the module in this section is still there, and the closure keyword is in, which is used to represent the function body of the closure that will follow, p1 > p2 is the body of the function, but the return keyword is omitted. Closure since parameter types and return value types to the compiler can be deduced from themselves, so the number of parameters editor is able to infer that, as a result, the parameter list is actually redundant, closure 1 will automatically generate some of the parameter name, and the parameters of the actual quantity to correspondence, such as closure of the above sort function has two parameters, the system will automatically generate $0 and $1 of these two parameters, the developer can use directly, because the parameter list will be omitted, so also no longer need closure keyword in to separate parameter list and the function body, at this time, The closure actually looks like this:


func onePuseTwo()->Int {
  return 1+2
}
onePuseTwo()
 You can also create functions that do not return a value: 

func sayHello(){
  print("Hello")
}
sayHello()

5

You read that correctly, and you put the left and right curly braces, and you have 1, 7 characters, and you have a sorting algorithm. I don't know if there's a second language that can do that besides Swift. Closure aside, there is also a syntax in Swift that defines operator methods for types, such as the String type by =, < . > For comparison, it is actually the class String that implements these operator methods. In a sense, one operator is similar to one function. Well, the method that needs to be passed into the sort function actually needs only one operator for some types.


func onePuseTwo()->Int {
  return 1+2
}
onePuseTwo()
 You can also create functions that do not return a value: 

func sayHello(){
  print("Hello")
}
sayHello()

6

This time you can be really shocked that the new sorting algorithm only takes 1 character, literally 1 character.

5. More features of closures in Swift

Swift closures and interesting features, 1 in the first closure is passed as a parameter to the other one in the function, so the conventional method is written in the closure of braces function argument list in parentheses, if the code is a lot of closure, then on the code structure view will become not too clear, in order to solve this problem, the Swift such provisions: if the closure parameters is the function of the last one, developers can pull the parentheses, achieve closure at the end of the function code, the sample is as follows:


func onePuseTwo()->Int {
  return 1+2
}
onePuseTwo()
 You can also create functions that do not return a value: 

func sayHello(){
  print("Hello")
}
sayHello()

7

If there is only one argument to a function and the argument is a closure, then the developer can use the closure ending notation to omit the argument list parenthesis. Here is an example:


func func3(param:()->Void)->Void{
  param()
  print(" Call the func3 function ")
}
func3{
  print(" The contents of the closure ")
}

Swift includes the concept of a closure to escape, this is easy to understand, when the closure as a parameter passed into the function, if the closure is used in the function, only the developers would declare the closure to the escape, which tell the system when this function after the closure of the statement cycle will end, the advantage is can improve the performance of the code USES the type of closure statement said the escape @ noescape keywords, the sample is as follows:


func onePuseTwo()->Int {
  return 1+2
}
onePuseTwo()
 You can also create functions that do not return a value: 

func sayHello(){
  print("Hello")
}
sayHello()

9

Runaway closures are often used for asynchronous operations. For example, this closure processes a network request asynchronously, and the closure's declaration cycle ends only when the request ends. Another interesting feature of the non-escaping closure is that if the self keyword is used internally, self can be omitted.

Closures can also be generated automatically. This closure is called an automatic closure. An automatic closure can automatically encapsulate an expression into a closure without the developer having to write the closure's curly braces. Here's an example:


// Automatic closure demo 
var list = [1,2,3,4,5,6]
// create 1 Two explicit closures 
let closures = {
  list.removeFirst()
  list.append(7)
}
// Will be printed [1,2,3,4,5,6]
print(list)
// Perform a closure 
closures()
// Will be printed [2,3,4,5,6,7]
print(list)
func func4(closure:()->Void) -> Void {
  // Performs an explicit closure 
  closures()
}
func func5(@autoclosure auto:()->Void) -> Void {
  // Perform an automatic closure 
  auto()
}
// Explicit closure   I need curly braces 
func4(closures)
// Will be printed [3,4,5,6,7,7]
print(list)
// The expression is automatically generated as a closure 
func5(list.append(8))
// Will be printed [3,4,5,6,7,7,8]
print(list)

Automatic closures are non-escape by default, and if you want to use a runaway closure, you need to declare it manually, as follows:


func func5(@autoclosure(escaping) auto:()->Void) -> Void {
  // Perform an automatic closure 
  auto()
}


Related articles: