Recently, I have read many tutorials and daishen’s blog during my study of Swift. Finally, I put my notes here for easy review

W3cschool -Swift tutorial, YungFan’s brief book (recommended to have a look, some knowledge summary is simply easy to understand)

A, functions,

1, the introduction

The function is the method in OC

General format:

Func function name (argument list) -> Return value type {code block return value}Copy the code

2, the format of a variety of cases

1. No parameter + no return value

Void {print("iPhone Xs Max")} Void {print("iPhone Xs Max")} Void {print("iPhone Xs Max")} About2 () {print("iPhone Xs Max")} about2() {print("iPhone Xs Max")} about2() {print("iPhone Xs Max")} about2()Copy the code

2. No parameter + return value

Func readMessage() -> String {return "Did you eat?" } var str = readMessage() print(str)Copy the code

3. There are arguments + no return values

Func call(phoneNum: String) {print(" call \(phoneNum)")} Call ("18888888888")Copy the code

4, there are arguments + return value

func sum(num1 : Int, num2 : Int) -> Int {
    return num1 + num2
}
var result = sum(num1: 20, num2: 30)
print(result)
Copy the code

5. Return a complex type

Func getInfo(info:String) -> (name:String, age:Int) {let infos = info. coments (separatedBy: ",") // Note that the second type is converted and added! return (infos[0], Int(infos[1])!) } let person:(name:String, age:Int) = getInfo(info: "zhangsan,20") print(person.name) print(person.age)Copy the code

3. Precautions

1. Function parameters are constants;

Parameter label + parameter name, that is, external parameter name + internal parameter name + type;

The conventional way of writing function arguments

func addFunc(num1 a: Int,num2 b: Int) -> Int {
    return a + b
}

let result = addFunc(num1: 5, num2: 5)

print(result) //10
Copy the code

Shorthand, ellipsis

func addFunc(_ a: Int,_ b: Int) -> Int {
    return a + b
}

let result = addFunc(5, 5)

print(result) //10
Copy the code

3. You can set default parameters (if no parameters are passed in).

Func makecoffee(type :String = "ice American ") -> String {return" Drink \(type). } let coffee1 = makecoffee(type: "latte ") print(coffee1) // Let coffee2 = makecoffee() print(coffee2)Copy the code

4. Variable parameters: the number of parameters accepted in SWIFT is uncertain, but the type should be the same;

func total(numbers:Int...) -> Int { var sum = 0 for i in numbers { sum += i } return sum } let res1 = total() let res2 = total(numbers:10) let res3 = total(numbers:10,20,30) print(numbers:10,20,30) print(numbers:10,20,30) print(numbers:10,20,30) print(numbers:10,20,30) print(numbers:10,20, 20) / / 60Copy the code

5, inout reference type: the general argument only passes a value, if you want to change the external argument to use inout, similar to the block __block;

func changeInt(a: inout Int, b: Print (" a=\(a), b=\(b)") print(" a=\(a), b=\(b)") print(" a=\(a), b=\(b)") & a, b, and b) print (" call: a = \ (a), b = \ "(b)) / / print: after the call: a = 22, b = 120Copy the code

Nesting of functions: nested functions can only be called within the function

4. Function types and nested functions

Each function has its own type 3. Define + use -> Code examples 4. Nested functions (one function as an argument to another function, one function as the return value of another function)

Use of function types:

// define a function func addTwoInts(a: Int, b: Int) -> Int {return a + b} // The function type is: (Int, Int) -> Int Let res = mathFunction(10, 20) print(res)Copy the code

A function as an argument to another function:

// define a function func addTwoInts(a: Int, b: Int) -> Int {return a + b} // The type of this function is: (Int, Int) -> Int // as an argument to another function // argument name: Func printResult(a: Int, b: Int, calculateMethod: (Int, Int) -> Int) {print(calculateMethod(a, b))} printResult(a: 10, b: 20, calculateMethod: PrintResult (a: 12, b: 22, calculateMethod: {(m: Int, n: Int) -> Int in return m + n})Copy the code

The return value of one function as another function:

(a: Int, b: Int) -> Int {return a + b} func multiplyTwoInt(a: Int, b: Int) Int) -> Int {return a * b} func getResult(a:Int) -> (Int, Int)->Int{if a > 10 {return addTwoInts} else{return multiplyTwoInt}} Print (res2) = getResult(a: 12)(10,20) print(res2) //Copy the code

Second, the closure

1, the introduction

Closure: a stand-alone module that can be passed and referenced;

It can capture and store any constants and variables defined in its context. That is, it closes and wraps its constants and variables, hence the name: closure

Closures, like functions, are reference types

Divided into three forms:

  • A global function is a closure that has a name but does not capture any values
  • An embedded function is a closure that has a name and can capture values from an upper function
  • Closure expressions, a lightweight syntax, capture nameless closures of constants and variable values in their context

2. Compare with functions

Compute a specific value of a number, such as a square

The way you write a function

Func square(num: Int) -> Int{return num * num}Copy the code

The way to write closure

Let squareCloure = {(num: Int) -> Int in return num * num}Copy the code
Actual combat scene

conditions

// This is a function, Func getList(score:[Int], getList(score:[Int], Con (Int)->Bool) -> [Int]{var newScore:[Int] = [Int]() for item in score { {} if con(item) {newscore.append (item)}} return newScore} let scoreArray = [75,60,95,45,85]Copy the code

Functional processing

Func method(num: Int) -> Bool{return num > 50} let newArrayM = getList(score: scoreArray, con: score: scoreArray) method) print(newArrayM) //[75, 60, 95, 85]Copy the code

Closure mode

Let closure = {(num: Int) -> Bool in return num > 50} let newArrayC = getList(score: scoreArray, con: score: scoreArray); Closure) print(newArrayC) //[75, 60, 95, 85] // Let newArrayC2 = getList(score: scoreArray, con:{(num: Int) -> Bool in return num > 50}) print(newArrayC2) //[75, 60, 95, 85]Copy the code

3. Main knowledge points

($0, $1, $2) ($0, $1, $2) ($0, $1, $2) ($0, $1, $2) ($0, $1, $2) ($0, $1, $2) ($0, $1, $2) ($0, $1, $2) ($0, $1, $2) ($0, $1, $2)

  • 1, ellipsis->andReturn value type(The return value is a Bool.)
let newArrayC2 = getList(score: scoreArray,  con:{(num: Int) in return num > 50})
Copy the code
  • 2, ellipsisThe parameter typesandparentheses(The function must pass an Int according to the parameter)
let newArrayC2 = getList(score: scoreArray,  con:{num in return num > 50})
Copy the code
  • 3, ellipsisreturn(Omit return because it is a single line statement)
let newArrayC2 = getList(score: scoreArray,  con:{num in num > 50})
Copy the code
  • 4. Omit the parameter nameParameter declarationsandin
let newArrayC2 = getList(score: scoreArray,  con:{$0 > 50})
Copy the code

4, capture

  • Closures can capture constants and variables from the context and use them in their own scope

  • The simplest form of closure for Swift is a nested function, that is, a function defined within the body of another function, which captures all of its external function’s parameters, as well as its defined constants and variables

Func makeIncrementor(forIncrement Amount: Int) -> () -> Int {var runningTotal = 0 func incrementor() -> Int {runningTotal += amount return runningTotal } return incrementor } let incrementByTen = makeIncrementor(forIncrement: Print (incrementByTen())// return 10Copy the code

5. Trailing closures

The closure format has been changed to improve readability

Condition: there is a function in which the closure is the last argument: omit the closure parameter and advance the parentheses, and use {} for closure pass-through benefits: increased readability

Example:

Func doSomething(info:String, clousre: String)->Void){clousre(info)} "Hello", clousre: {STR in print(STR)}) doSomething(info: "World") {STR in print(STR)}Copy the code

6. Escape closure

Using @escaping to precede the closure parameter type indicates that this is a escaping closure that will be called after the function ends.

Purpose: Escape closures are commonly used for asynchronous callbacks

Var closureArray :[()->Void] = [()->Void]() Func normolClosure(closure ()->Void){closure()} // Define a function that takes an escape closure and stores the closure in an array, but does not call it. Func escapeClosure(Closure: @escaping ()->Void){print(" function begins ") ClosureArray.append (Closure) print(" function ends ")} print(" Before calling function, NormolClosure {x = 100} // normolClosure {x = 100} // normolClosure {x = 100} EscapeClosure {x = 200} print(" < escapeClosure < x = 200}) Check x = \(x)") // Call the escape closure closureArray.first outside the function? () print(" x = \(x)") /* print: So before we call the function, we check that x is 10 and after we call the normal closure, we check that x is 100 and after we call the escape closure, we check that x is 100 and we call the escape closure outside of the function, we check that x is 200 */Copy the code

7. Automatic closures

Using @Autoclosure before the closure parameter type indicates that this is an automatic closure.

An expression used to wrap function arguments that takes no arguments and returns the value of the wrapped expression when called

// Automatic closure func printIfTrue(predicate: @Autoclosure ()->Bool){if predicate() {print("is true")} else{print("is false")} } // Swift will automatically convert 2 > 1 to () -> Bool. This gives us a simple and clear expression. printIfTrue(predicate: 2>1) printIfTrue(predicate: 2<1)Copy the code

8. Solve circular references

Plan 1: Weak

  • Weak reference to the current class with the weak modifier self

  • Self is a case that may or may not have a value, so weakSelf is an optional type

  • And since the current self must exist, or it wouldn’t be in the method at all, you can use forced unpacking (!) when calling it. .

Weak var weakSelf = self someView.block = {// Execute a method of the current class weakSelf! .refreshView() }Copy the code

Plan 2: Also weak, which is short for Plan 1

Someview. block = {[weak self] in // execute some method of the current class self? .refreshView() }Copy the code

Plan 3: unowned

  • unowned is similar to unsafe_unretained in OC

  • This means that even if the object it originally referred to is freed, the throw retains an invalid reference to the freed object, so it cannot be optional and does not refer to nil

Someview.block = {[unowned self] in // Execute a method of the current class self.refreshView()}Copy the code