function
Definition of a function
A function that returns a value
The default parameter is let and can only be let
func sum(v1: Int, v2: Int) -> Int {
return v1 + v2
}
Copy the code
A function that returns no value
Essentially an empty tuple returns the value
SayHello () -> Void {} sayHello() -> () {} sayHello() {} sayHello() {} sayHello();Copy the code
Implicit return
If the whole function body is a single expression, the function implicitly returns that expression
func sum(v1: Int, v2: Int) -> Int { v1 + v2 }
sum(v1: 10, v2: 20)
Copy the code
Returns a tuple that implements multiple return values
func calculate(v1: Int, v2: Int) -> (sum: Int, difference: Int, average: Int) {
let sum = v1 + v2
return (sum, v1 - v2, sum >> 1)
}
let result = calculate(v1: 20, v2: 10)
print(result.sum, result.difference, result.average)
Copy the code
Documentation of the function
Notes can be written in a certain format for easy reading
/// /// -parameter v1: the first integer /// -parameter v2: the second integer /// -parameter v2: the second integer /// /// /// - Note: func sum(v1: Int, v2: Int) -> Int {v1 + v2}Copy the code
Refer to Apple’s official API design guidelines in detail
Argument Label
You can modify the parameter label
func gotoWork(at time: String) {
}
gotoWork(at: "8:00")
Copy the code
Parameter labels can be omitted, but are generally not recommended for readability
func sum(_ value1: Int, _ value2: Int) -> Int {
value1 + value2
}
sum(5, 5)
Copy the code
Default Parameter Value
Parameters can have default values
func check(name: String = "nobody", age: Int, job: String = "none") {
print("name=\(name), age=\(age), job=\(job)")
}
check(name: "Jack", age: 20, job: "Doctor")
check(name: "Jack", age: 20)
check(age: 20, job: "Doctor")
check(age: 20)
Copy the code
C++ default parameter values have a limitation: they must be set from right to left; Because Swift has parameter labels, there are no such restrictions
However, you need to be careful when omitting parameter labels to avoid errors
Func test(_ first: Int = 10, middle: Int, _ last: Int = 30) {} test(middle: 20)Copy the code
Variadic Parameter
A function can have at most one variable argument
func sum(_ numbers: Int...) -> Int {
numbers.count
}
sum(1, 2, 3, 4)
Copy the code
Parameters immediately following a variable parameter cannot omit the parameter label
Func get(_ number: Int... , string: String, _ other: String) { } get(10, 20, string: "Jack", "Rose")Copy the code
Take a look at Swift’s print function
print(1, 2, 3, 4, 5)
print(1, 2, 3, 4, 5, separator: " ", terminator: "\n")
Copy the code
In-out Parameter
You can use inout to define an input and output parameter: you can modify the values of external arguments inside the function
func swapValues(_ v1: inout Int, _ v2: inout Int) {
let tmp = v1
v1 = v2
v2 = tmp
}
var num1 = 10
var num2 = 20
swapValues(&num1, &num2)
Copy the code
The official swap function is inout
You can use tuples to exchange parameters
func swapValues(_ v1: inout Int, _ v2: inout Int) {
(v1, v2) = (v2, v1)
}
var num1 = 10
var num2 = 20
swapValues(&num1, &num2)
Copy the code
Variable arguments cannot be marked as inout
The inout parameter cannot have a default value
An inout argument can only be passed in that can be assigned multiple times
Constants can only be assigned once when they are defined, so an error is reported below
The nature of the inout argument is address passing
Let’s create a new project and disassemble it to see its essence
Leaq stands for address passing. You can see that the addresses of the two variables are placed in registers before calling the function
Function Overload
Rules for function overloading
- Same function name
- Parameter number different | | parameter types different | | parameters different tags
Func sum(value1: Int, value2: Int) -> Int {} // Different number of arguments func sum(_ value1: Int, _ value2: Int, _ value3: Int sum(_ a: Int, _ b: Int) -> Int {} func sum(_ a: Int, _ b: Int) -> Int {} Double) -> Int { }Copy the code
Return value types are independent of function overloading
The compiler does not raise an error when using default parameter values with function overloading to generate ambiguities (it does in C++)
Func sum(_ value1: Int, _ value2: Int, _ value3: Int = 5) -> Int {v1 + v2 + v3} func sum(_ value1: Int, _ value2: Int, _ value3: Int = 5) -> Int {v1 + v2 + v3} Int, _ value2: Int) -> Int {v1 + v2}Copy the code
When mutable arguments, omitted parameter labels, and function overloading are used together to produce ambiguities, the compiler may raise an error
Inline functions
If compiler optimization is enabled (which is enabled by default in Release mode), the compiler will automatically make some functions inline
What does the compiler do to change tuning options in Debug mode
1. Let’s create a new project. The project code is as follows
2. We then disassemble to see what the compiler does when it is not optimized
As you can see, the test function is called, and then the print is performed inside the test function
3. Now let’s turn on optimization options in the Debug model and run the program
It was found that print was directly executed in main function without the call process of test function
This is equivalent to putting print directly inside main, and the compiler expands the function call into the function body
Which functions are not inlined
- The body of the function is longer
- Contains recursive calls
- Includes dynamic dispatch (polymorphic calls at runtime)
We can use@inline
Keyword to actively control whether the compiler does optimizations
@inline(nerver) : will never be inline, even if compiler optimization is turned on
@inline(nerver) func test() {}
Copy the code
@inline(__alaways) : When compiler optimization is enabled, long code will be inlined (except for recursive calls and dynamic dispatch)
@inline(__alaways) func test() {}
Copy the code
In Release mode, the compiler already has optimization enabled and will automatically determine which functions need to be inline, so @inline is not necessary
Function Type
Every function has a type. A function type consists of a parameter type and a return value type
/ / () - > Void or () - > () func test () {} / / (Int, Int) - > Int func sum (a: Int, b: Int) - > Int {} / / define variables var fn: (Int, Int) -> Int = sum fn(5, 3Copy the code
Function types as function parameters
func sum(v1: Int, v2: Int) -> Int {
v1 + v2
}
func difference(v1: Int, v2: Int) -> Int {
v1 - v2
}
func printResult(_ mathFn: (Int, Int) -> Int, _ a: Int, _ b: Int) {
mathFn(a, b)
}
printResult(sum, 5, 2)
printResult(difference, 5, 2)
Copy the code
Function type as function return value
func next(_ input: Int) -> Int {
input + 1
}
func previous(_ input: Int) -> Int {
input - 1
}
func forward(_ forward: Bool) -> (Int) -> Int {
forward ? next : previous
}
forward(true)(3)
forward(false)(3)
Copy the code
A function whose return value is a function type is called a higher-order function
typealias
Used to alias a type
typealias Byte = Int8
typealias Short = Int16
typealias Long = Int64
typealias Date = (year: String, mouth: String, day: String)
func getDate(_ date: Date) {
print(date.day)
print(date.0)
}
getDate(("2011", "9", "10"))
typealias IntFn = (Int, Int) -> Int
func difference(v1: Int, v2: Int) -> Int {
v1 - v2
}
let fn: IntFn = difference
fn(20, 10)
func setFn(_ fn: IntFn) { }
setFn(difference)
func getFn() -> IntFn { difference }
Copy the code
The Swift library defines Void as an empty tuple ()
Nested function
Define a function inside a function
func forward(_ forward: Bool) -> (Int) -> Int {
func next(_ input: Int) -> Int {
input + 1
}
func previous(_ input: Int) -> Int {
input - 1
}
forward ? next : previous
}
forward(true)(3)
forward(false)(3)
Copy the code
(Optional)
Optional, also commonly called optional types, allow values to be set to nil
Put a question mark after the type name? To define an optional
var name: String? = nil
Copy the code
If the optional type is defined without a given value, the default value is nil
var age: Int? Equivalent to var age: Int? = nilCopy the code
If the Optional type is assigned when it is defined, it is an Optional value
var name: String? = "Jack" // Optional(Jack)
Copy the code
Optional types can also be used as function return values
var array = [1, 2, 3, 4]
func get(_ index: Int) -> Int? {
if index < 0 || index >= array.count {
return nil
}
return array[index]
}
Copy the code
Forced Unwrapping
Optional is a layer of packaging on other types, which can be understood as a box
- If it is
nil
So it’s an empty box - If not for
nil
The box contains the type of data to be wrapped
var age: Int?
age = 10
age = nil
Copy the code
The types of optional relationships are roughly shown below
If you want to take wrapped data out of the options (take the contents of the box out), use an exclamation point! Forced unpack
var age: Int? = 10 var ageInt = age! AgeInt += 10 // ageInt is an IntCopy the code
Forced unpacking of an optional (empty box) with a value of nil will result in a runtime error
Optional Binding
We can determine if the optional contains a value
Let number = Int("123") // number = Int? if number ! = nil { print(number!) }Copy the code
Optional bindings can also be used to determine whether optional options contain values
If it does, it is automatically unpacked, assigns the value to a temporary constant (let) or variable (var), and returns true, otherwise returns false
If let number = Int("123") {print(" \(number)") // number is forced to unpack the Int value // number scope is limited to this curly bracket} else {print(" string to integer failed ")}Copy the code
If there are multiple criteria, you can combine them and use commas to separate them
if let first = Int("4") { if let second = Int("42") { if first < second && second < 100 { print("\(first) < \(second) < Let first = Int("4"), let second = Int("42"), first < second && second < 100 { print("\(first) < \(second) < 100") }Copy the code
Optional bindings are used in the while loop
let strs = ["10", "20", "abc", "-20", "30"]
var index = 0
var sum = 0
while let num = Int(strs[index]),
num > 0 {
sum += num
index += 1
}
Copy the code
The Nil-Coalescing Operator
We can use the null merge operator?? To check if the previous value has a value, and if the previous value is nil, it returns the later value
Detailed usage is as follows
a ?? B is optional b is optional or not optional B has to be of the same storage type as A if a is not nil return A if a is nil return B if B is not optional return A and it will be unpacked automaticallyCopy the code
The type of results depends on?? What is the following value type
let a: Int? = 1 let b: Int = 2 let c = a ?? B // c is Int, 1 let a: Int? = nil let b: Int = 2 let c = a ?? B // c is Int, 2Copy the code
More than one?? Used together
let a: Int? = 1
let b: Int? = 2
let c = a ?? b ?? 3
let a: Int? = nil
let b: Int? = 2
let c = a ?? b ?? 3
Copy the code
var a: Int??? = 10
var b: Int = 20
var c: Int? = 30
print(a ?? b) // Optional(Optional(10))
print(a ?? c) // Optional(Optional(10))
Copy the code
?? Used in conjunction with if let
let a: Int? = nil
let b: Int? = 2
if let c = a ?? b {
print(c)
}
if let c = a, let d = b {
print(c)
print(d)
}
Copy the code
Guard statement
When the guard statement condition is false, the code inside the braces is executed
When the guard statement condition is true, the guard statement is skipped
The GUARD statement is suitable for “early exit”
Guard condition else {// do something.... Exit current scope // return}Copy the code
When guard statements are used for optional binding, bound constants (lets) and variables (var) can also be used in outer scopes
func login(_ info: [String : String]) {guard let username = info["username"] else {print(" please input username") return} Guard let password = info["password"] Else {print(" Please enter password ") return} // if username.... // if password .... Print (username: \ "(username)", "password: \ (password)," login "ing")}Copy the code
Implicitly Unwrapped Optional
In some cases, an option will always have a value once it has been set
In this case, the checking can be removed, and it does not have to be unpacked every time it is accessed, because it can be sure that it has a value every time it is accessed
You can put an exclamation mark after the type! Defines an implicit unpacking option
let num1: Int! = 10 let num2: Int = num1 if num1 ! = nil { print(num1 + 6) } if let num3 = num1 { print(num3) }Copy the code
An error is also reported if an option with a null value is implicitly unpacked
Optional types of implicit unpacking, most want someone to give a value that is not null, if someone passed a null value that is an error, the purpose is to make your rules, more suitable for making an interface to receive arguments;
It is recommended not to use this type
String interpolation
Optional The compiler will warn if the string is interpolated or printed directly
There are at least three ways to eliminate warnings
var age: Int? = 10 print("My age is \(age!) ") // My age is 10 print("My age is \(String(describing: age))") // My age is Optional(10) print("My age is \(age ?? 0)") // My age is 10Copy the code
Multiple options
1. Look at the following optional types, which can be interpreted using the following pictures
var num1: Int? = 10
var num2: Int?? = num1
var num3: Int?? = 10
print(num2 == num3) // true
Copy the code
Use the LLDB directive frame variable-r or fr V-r to check the difference
2. Look at the following optional types, which can be interpreted using the following pictures
var num1: Int? = nil var num2: Int?? = num1 var num3: Int?? = nil print(num2 == num3) // false print(num3 == num1) // false (because the type is different) 1)?? 2 // 2 (num3 ?? 1)?? 2 / / 1Copy the code
No matter how many layers are optional, once you assign nil, there’s only one big outer box
Use the LLDB directive frame variable-r or fr V-r to check the difference