Swift for iOS Development (6)-Function

version

Xcode 11.0
Swift 5.1

Function definition and call

A function is an independent piece of code that accomplishes a specific task.
When you define a function, you can define one or more values ​​with names and types as the input to the function, called parameters, or you can define a certain type of value as the output at the end of the function execution, called the return type .
The function can have no parameters or return type.
General writing

func 函数名(形参1, 形参2) -> 返回类型 {
    
    
    // 函数体
}

for example:

// 定义
func funcName(name: String, address: String) -> String {
    
    
    return name + "住在" + address
}

// 调用
print(funcName(name: "小明", address: "和磡村"))
// 打印 小明住在和磡村

Parameters and return values

1. No parameters

// 无参数
func sayHello() -> String {
    
    
    return "Hello, world"
}
print(sayHello())
// 打印 Hello, world

Although this function has no parameters, a pair of parentheses is required after the function name in the definition. When called, it is also necessary to write a pair of parentheses after the function name.

2. Multiple parameters

// 多参数
func teamMember(name1: String, name2: String, name3: String) -> String {
    
    
    return "团队成员有" + name1 + "," + name2 + "," + name3
}
print(teamMember(name1: "小明", name2: "小红", name3: "小黑"))
// 打印 团队成员有小明,小红,小黑

3. No return value

// 无返回值
func printTeamMember(name1: String, name2: String, name3: String) {
    
    
    print("团队成员有\(name1), \(name2), \(name3)")
}
printTeamMember(name1: "小明", name2: "小红", name3: "小黑")
// 打印 团队成员有小明, 小红, 小黑

Strictly speaking, even if the return value is not clearly defined, the function still returns a value. Functions without a clearly defined return type return a special value of type Void, which is an empty tuple, written as ().

4. Multiple return values ​​(return tuple type) In the
following example, a function named minMax(array:) is defined, which is used to find the minimum and maximum values ​​in an Int type array.

// 定义
func minMax(array: [Int]) -> (min: Int, max: Int) {
    
    
    var currentMin = array[0]
    var currentMax = array[0]
    for value in array[1..<array.count] {
    
    
        if value < currentMin {
    
    
            currentMin = value
        } else if value > currentMax {
    
    
            currentMax = value
        }
    }
    return (currentMin, currentMax)
}

// 调用
let bounds = minMax(array: [8, -6, 2, 109, 3, 71])
print("min is \(bounds.min) and max is \(bounds.max)")
// 打印“min is -6 and max is 109”

5. Optional tuple return type
If the tuple type returned by the function may have "no value" for the entire tuple, you can use the optional tuple return type to reflect the fact that the entire tuple can be nil. You can define an optional tuple by placing a question mark after the closing parenthesis of the tuple type, such as (Int, Int)? or (String, Int, Bool)?

Note that
optional tuple types such as (Int, Int)? and tuples containing optional types such as (Int?, Int?) are different. Optional tuple type. The entire tuple is optional, not just the value of each element in the tuple.

The previous minMax(array:) function returns a tuple containing two Int values. But the function does not perform any security checks on the passed array. If the array parameter is an empty array, minMax(array:) defined above will trigger a runtime error when trying to access array[0].
To safely handle this "empty array" problem, rewrite the minMax(array:) function to use an optional tuple return type, and return nil when the array is empty:

func minMax(array: [Int]) -> (min: Int, max: Int)? {
    
    
    if array.isEmpty {
    
     return nil }
    var currentMin = array[0]
    var currentMax = array[0]
    for value in array[1..<array.count] {
    
    
        if value < currentMin {
    
    
            currentMin = value
        } else if value > currentMax {
    
    
            currentMax = value
        }
    }
    return (currentMin, currentMax)
}

if let bounds = minMax(array: [8, -6, 2, 109, 3, 71]) {
    
    
    print("min is \(bounds.min) and max is \(bounds.max)")
}
// 打印“min is -6 and max is 109”

Parameter label and parameter name

1. Parameter label
We can write the example at the beginning of the article like this:

// 函数标签
func funcName1(student name: String, liveIn address: String) -> String {
    
    
    return "学生" + name + "住在" + address
}
print(funcName1(student: "小明", liveIn: "和磡村"))
// 打印 学生小明住在和磡村

The parameter name is preceded by a label student, and the parameter address is preceded by a label liveIn.
Before labeling, the function is called with the parameter name; after labeling, the parameter label must be used.

2. Ignore parameter labels
If you don't want to add a label to a parameter, you can use an underscore (_) instead of an explicit parameter label.

// 忽略函数标签
func funcName2(_ name: String, _ address: String) -> String {
    
    
    return "学生" + name + "住在" + address
}
print(funcName2("小明", "和磡村"))
// 打印 学生小明住在和磡村

3. Default parameter value
You can define a default value (Deafult Value) for any parameter by assigning a value to the parameter in the function body. When the default value is defined, this parameter can be ignored when calling this function.

// 默认参数值
func funcName3(name: String, address: String = "和磡村") -> String {
    
    
    return "学生" + name + "住在" + address
}
print(funcName3(name: "小明"))
// 打印 学生小明住在和磡村
print(funcName3(name: "小明", address: "白石洲"))
// 打印 学生小明住在白石洲

4. Variable parameters
A variable parameter (variadic parameter) can accept zero or more values. When calling a function, you can use variable parameters to specify that the function parameters can be passed an indeterminate number of input values. Define variable parameters by adding (...) after the variable type name.

// 可变参数
func funcName4(names: String..., address: String) -> String {
    
    
    var str = "学生"
    for name in names[0...] {
    
    
        str.append(name)
        str.append(" ")
    }
    str.append("住在")
    str.append(address)
    return str
}
print(funcName4(names: "小明", "小红", "小黑", address: "和磡村"))
// 打印 学生小明 小红 小黑 住在和磡村

Note:
There can only be one variable parameter in a function. The old version of Swift can only have the last parameter, and the new version is not limited.

5. Input and output parameters
Function parameters are constants by default.
When defining an input and output parameter, add the inout keyword before the parameter definition, and add an ampersand before the parameter name when passing in the parameter.

// 输入输出参数
func assignment(number1: inout Int, number2: inout Int) {
    
    
    number1 = 20
    number2 = 30
}
var int1 = 0, int2 = 0
assignment(number1: &int1, number2: &int2)
print("int1 = \(int1), int2 = \(int2)")
// 打印 int1 = 20, int2 = 30

Function type

Each function has a specific function type, and the function type is composed of the function's parameter type and return type.
E.g:

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

The type of this function is (Int, Int) -> Int, which can be interpreted as:
"This function type has two Int-type parameters and returns an Int-type value".

Another example:

func printHelloWorld() {
    
    
    print("hello, world")
}

The type of this function is: () -> Void, or "a function that has no parameters and returns a Void".

1. Using function types
In Swift, using function types is just like using other types. For example, you can define a constant or variable of type function and assign the appropriate function to it:

var mathFunction: (Int, Int) -> Int = addTwoInts

addTwoInts and mathFunction have the same type, so this assignment process is allowed in Swift type-check.
Now, you can use mathFunction to call the assigned function:

print("Result: \(mathFunction(2, 3))")
// Prints "Result: 5"

Just like other types, when assigning a function to a constant or variable, you can let Swift infer the function type:

let anotherMathFunction = addTwoInts
// anotherMathFunction 被推断为 (Int, Int) -> Int 类型

2. Function type as the parameter type
You can use the function type (Int, Int) -> Int as the parameter type of another function. This way you can leave part of the function's implementation to the caller of the function to provide.
Here is another example, just like the function above, it also outputs the result of a certain mathematical operation:

func printMathResult(_ mathFunction: (Int, Int) -> Int, _ a: Int, _ b: Int) {
    
    
    print("Result: \(mathFunction(a, b))")
}
printMathResult(addTwoInts, 3, 5)
// 打印“Result: 8”

This example defines printMathResult ( : : :) function, which takes three parameters: The first parameter called mathFunction, type (Int, Int) -> Int , you can pass any of this type of function; the second and The third parameters are called a and b, and their types are both Int. These two values ​​are used as the input values ​​of the given function.
When printMathResult (
: : :) is invoked, it is passed addTwoInts function and an integer of 3 and 5. It calls addTwoInts with 3 and 5, and outputs the result: 8.

3. Function type as the return type
You can use the function type as the return type of another function. What you need to do is write a complete function type after the return arrow (->).
In the following example, two simple functions are defined, namely stepForward( :) and stepBackward( : ). The stepForward(:) function returns a value that is 1 greater than the input value. The stepBackward(:) function returns a value that is one less than the input value. The types of these two functions are both (Int) -> Int:

func stepForward(_ input: Int) -> Int {
    
    
    return input + 1
}
func stepBackward(_ input: Int) -> Int {
    
    
    return input - 1
}

The following function named chooseStepFunction(backward:), its return type is (Int) -> Int type function. chooseStepFunction(backward:) returns the stepForward(:) function or stepBackward( :) function according to the Boolean value backwards :

func chooseStepFunction(backward: Bool) -> (Int) -> Int {
    
    
    return backward ? stepBackward : stepForward
}

You can now use chooseStepFunction(backward:) to get one of the two functions:

var currentValue = 3
let moveNearerToZero = chooseStepFunction(backward: currentValue > 0)
// moveNearerToZero 现在指向 stepBackward() 函数。

In the above example, it is calculated whether the currentValue gradually approaches 0 to a positive number or a negative number. The initial value of currentValue is 3, which means that currentValue> 0 is true, which will make chooseStepFunction( :) return the stepBackward(:) function. A reference to the returned function is stored in the moveNearerToZero constant.
Now, moveNearerToZero points to the correct function, which can be used to count to zero:

print("Counting to zero:")
// Counting to zero:
while currentValue != 0 {
    
    
    print("\(currentValue)... ")
    currentValue = moveNearerToZero(currentValue)
}
print("zero!")
// 3...
// 2...
// 1...
// zero!

Nested function

All the functions you have seen so far in this chapter are called global functions, and they are defined in the global domain. You can also define functions in other function bodies, called nested functions.
By default, nested functions are invisible to the outside world, but can be called by their enclosing functions. A peripheral function can also return one of its nested functions, so that this function can be used in other domains.
You can rewrite the chooseStepFunction(backward:) function to return a nested function:

func chooseStepFunction(backward: Bool) -> (Int) -> Int {
    
    
    func stepForward(input: Int) -> Int {
    
     return input + 1 }
    func stepBackward(input: Int) -> Int {
    
     return input - 1 }
    return backward ? stepBackward : stepForward
}
var currentValue = -4
let moveNearerToZero = chooseStepFunction(backward: currentValue > 0)
// moveNearerToZero now refers to the nested stepForward() function
while currentValue != 0 {
    
    
    print("\(currentValue)... ")
    currentValue = moveNearerToZero(currentValue)
}
print("zero!")
// -4...
// -3...
// -2...
// -1...
// zero!

Guess you like

Origin blog.csdn.net/u012078168/article/details/103700671