1. The function

1.1 Function Format:

1). Multiple returns: func function name (parameter name: parameter type…) -> (Return value type…) {} 2). Single return value: func function name (parameter name: parameter type…) -> Return value type {} 3). No return value: func function name (parameter name: parameter type,…) -> () or func function name (parameter name: parameter type,…) Public TypeAlias Void = () public TypeAlias Void = ()

1). The default parameter is let and can only be let; 2). Implement multiple function return values, using the Tuple type in Swift

1.2 Initial Parameter Values

Parameter Settings Initial Value Parameter name: Parameter type = Initial value

func person(name:String ,age : Int.job : String = "free worker"){
    print("name = \(name),age = \(age),job = \(job)")}Copy the code

After declaring the function above, you can see when calling the function:

A parameter with an initial value may or may not be passed a value when the function is called.

1.3 Variadic Parameter

Format: Parameter Name: Parameter Type…

Note: 1). Only one variable argument can exist in each function; 3). The parameter name of a variable parameter can be omitted. 4). Omit parameter labels and variable parameter types are the same, do not declare consecutively, it is difficult to distinguish which parameter is given

func makeSentence(words : String. .other:String) -> String{
    var sentence = ""
    for word in words {
        sentence = sentence + "" + word
    }
    sentence = sentence + other
    return sentence
}
makeSentence(words: "Function"."having"."Variadic parameters"."Add as many strings here you want"."Can use one variadic parameter per func"."Make full use",other:".")
Copy the code

1.4 Argument Label

Parameter labels can be modified; 1). The parameter label format is: func function name (parameter label parameter name: parameter type…) -> (return list){}

2). Omit parameter label format: func function name (_ parameter name: parameter type,…) -> (return list){} This time after the declaration of the function instance variable, the parameter name is not displayed.

1.5 Implicit Return

If the entire function body is a single expression, the function implicitly returns the entire expression, in which case the return keyword can be omitted.

An 🌰 :

func sum(v1 : Int.v2 : Int) -> Int{
    v1 + v2
}
Copy the code

The sum function is v1 + v2; Is a single expression that can omit the return keyword.

1.6 Function Overload

Function overloading rules: 1). The function name is the same as 2). The number of parameters of different | | parameter types different | | parameters different tags

An 🌰 :

    / / function
    func sum(v1:Int.v2:Int)-> Int{
        v1 + v2
    }
    // Parameter labels are different
    func sum(_ v1 : Int._ v2 : Int) -> Int{
        v1 + v2
    }
    func sum(a : Int.b : Int) -> Int{
        a + b
    }
    // Different number of parameters
    func sum(v1:Int.v2:Int.v3:Int)-> Int{
        v1 + v2 + v3
    }
    // Different parameter types
    func sum(v1:Int.v2:Double) -> Double{
        Double(v1) + v2
    }
    func sum(v1:Double.v2:Int)-> Double{
        v1 + Double(v2)
    }
Copy the code

Tips: Return value types are independent of function overloading

func sum(v1:Int.v2:Int) -> Int{v1+v2}
func sum(v1:Int.v2:Int){}
sum(v1:10,v2:20)// Error: Ambiguous use of sum(v1:v2)
Copy the code

The above return values are of different types and do not constitute function overloading.

1.6 Using Functions

Function types are composed of the following types: formal parameter types, return value types function types can be parameters, return value;

1.6.1 Functions are defined as variables and constants

An 🌰 :

/ / square
func square(_ num : Int) -> Int{
    return num * num
}
square(4)
/ / cubic
func cube(_ num : Int) -> Int{
    return num * num * num
}
cube(4)
// You can assign a function to a variable or constant in the same way as square
var exponentialFunction = square
exponentialFunction(4)
// Print the result: 16
cube(exponentialFunction(4))
// Print the result: 4092
Copy the code

1.6.2 Function as input parameter

var integers = [1.2.3.4.5]
func sumOfExponentialsOf(array a: [Int].with function: (Int) - >Int)->Int
{
    var result = 0
    for x in a
    {
        result = result + function(x)
    }
    return result
}
sumOfExponentialsOf(array: integers, with: exponentialFunction)
// Print the result: 55
Copy the code

1.6.2 Function as return

A Function whose return type is a Function is called higher-order Function.

1. Nested Function

To define a function inside a function is called a nested function

For example 🌰 : define a function that returns a value of type function and has nested functions inside

func chooseComputation(isSquared b : Bool)- > (Int) - >Int{
    func square(_ num :Int)->Int// Nested functions
    {
        return num*num
    }
    func cube(_ num :Int)->Int
    {
        return num*num*num
    }
    if b {
        return square
    }
    else{
        return cube
    }
}
var result = chooseComputation(isSquared: true)//result is a function of type (Int)->(Int)
result(2) // Print the result: 4
result = chooseComputation(isSquared: false)
result(2) // Print the result: 8

let value = chooseComputation(isSquared: true) (5)// Value is an Int, and the output is 25
Copy the code

2. The structure of the body

In Swift, most common types are structures, including Bool, Int, Double, String, Array, Dictionary, and other common types. The structure has several distinct characteristics:

Feature 1: All constructs have an initializer (initializer, initializer, constructor, constructor) automatically generated by the compiler.

struct Rectangle{
   var width
   var height
}
var rectangle = Rectangle.init(width: 10, height: 10)
Copy the code

Attribute 2: Depending on the situation, the compiler may generate multiple initializers for a structure. The purpose is to ensure that all members have initial values.

An 🌰 1:

struct Rectangle{
    var width : Int = 10
    var height : Int
}
// Initial method 1:
var rectangle = Rectangle(width: 20, height: 20)

// Initial method 2:
var rectangle2 = Rectangle(height: 10)
Copy the code

For example, 🌰2: width and height are nil by default, equivalent to struct member variables having values

struct Rectangle{
    var width : Int?
    var height : Int?
}
// Initial method 1:
var rectangle = Rectangle(width: 20, height: 20)
// Initial method 2:
var rectangle2 = Rectangle(height: 10)
// Initial method 3:
var rectangle3 = Rectangle(a)Copy the code

Attribute 3: If the initialized structure is a constant, it cannot be changed, even if the structure members are variables


let rectangleConstant = Rectangle()
rectangleConstant.height = 20/ / an error
rectangleConstant.width = 20/ / an error
Copy the code

Attribute 4: If the initialized structure is a variable and the structure members are constants, the structure members cannot be changed

struct Circle{
    let radius : Int = 0
}
var circle = Circle()
circle.radius = 10/ / an error
Copy the code

Feature 4: Once you define an initializer when defining a structure, the compiler does not automatically generate additional initializers for the structure.

Class 3.

2) The class definition is similar to the structure, but the compiler does not automatically generate initializers for the class that can pass in member values. 3) If all members of a class have specified initializers when they are defined, the compiler generates an initializer with no parameters for the class. 4) The memory of the class stores: reference type information (8 bytes) + reference count (8 bytes) + variable; Methods in a class are not stored in the class’s memory. 5) The class memory alignment coefficient is 16.

4. The difference between structures and classes

1) Structs are value types (enumerations are also value types) and classes are reference types (pointer types); 2) Compilation automatically generates initialization methods for structs; 3) The internal storage of the structure may not be in the stack space, depending on where the structure variable is defined. If the structure variable is defined in a function, the structure variable is in the stack space. 4) The declared class variable is a pointer variable that points to the class stored in the heap. Classes must exist in heap space, class variables may not, depending on where class variables are defined.

5. Value types & reference types

5.1 value type

2) In order to improve the performance, String, Array, Dictionary, and Set adopt the technology of copy On Write. A copy operation is performed only when a write operation is performed. 3) Value types include: enumeration (Optional), structure (Bool, Int, Float, Double, Character), Array, Dictionary, Set.

5.2 Reference Types

  1. Class is a reference type
  2. When a reference is assigned to a var, let, or function, it makes a shallow copy of the memory address.

6. Closure

Functions are also a type of closure; Closures are functions that have no name and no func keyword.

6.1 Closure Expressions

Closure expressions:

{(parameter list) -> Return value typeinFunction body code}Copy the code

Additional: 1) Omit the return value type part when there is no return value, or the return value type can be inferred from the context; 2) Omit the argument list section of the code when there is no input parameter, or when the input parameter type can be inferred from the context

6.2 Trailing closures

A trailing closure is a closure expression written outside (after) the function call parentheses. Map and sorted are also trailing closures.

// Convert an integer array to a character array
var numbersArray = [1.2.3.4.5.6]
var closureString = numbersArray.map{
    return "\ [$0)"
}
print(closureString)// Print result: ["1", "2", "3", "4", "5", "6"]

// Sort arrays in descending order using trailing closures
var descendingArray = numbersArray.sorted{$0 > The $1}
print(descendingArray)// Print the result: [6, 5, 4, 3, 2, 1]
Copy the code

6.3 Escape (escape) closure

1) Escape closure: a closure passed to a function that will not be called until the function has finished executing. In other words, it outlives the function passed to it. Escape closures are typically used to complete handlers because they are called after the function ends. 2) Non-escaped closure: the closure of the passed function that will be called during the execution of the function, i.e. before it returns. Closures are not escaped by default and require the key @escaping modifier.

6.4 Automatic Closures (@AutoClosure)

An automatic closure is a closure that is automatically created to package expressions passed to functions as actual arguments. It takes no actual arguments, and when it is called, it returns the value of the internally packaged expression. The nice thing about this syntax is that it lets you omit the parentheses of function-form arguments by writing plain expressions instead of showing closures. An 🌰 :

// @autoclosure was not added
func getFirstPositive(_ v1:Int._ v2: () - >Int) -> Int? {return v1 > 0 ? v1 : v2()
}
getFirstPositive(-4) {20}

// Add @autoclosure
func getFirstPositive(_ v1:Int._ v2:@autoclosure() - >Int) -> Int? {return v1 > 0 ? v1 : v2()
}
getFirstPositive(-4.20)
Copy the code

Additional: @AutoClosure only supports arguments in ()-> T format; Null merge operator?? Using @Autoclosure technology; @autoclosure and no @Autoclosure constitute function overloading;