[关闭]
@kakadee 2017-04-19T02:54:04.000000Z 字数 6712 阅读 1396

Swift 3.0 学习笔记-5-函数

iOS Swift


前言:
swift3.0 学习笔记主要参考苹果开发者官网The Swift Programming Language (Swift 3.1)教程 以及 Swift 中文网
更纯粹的阅读的体验请移步至:
https://www.zybuluo.com/kakadee/note/727524



函数是执行特定任务的代码自包含块。给定一个函数名称标识, 当执行其任务时就可以用这个标识来进行"调用"。

1. 函数的声明与调用

当你定义一个函数时,你可以为其定义一个或多个命名,定义类型值作为函数的输入(称为参数),当该函数完成时将传回输出定义的类型(称为作为它的返回类型)。
下面是一个greet(person:)函数,输入参数是一个名字叫personString类型。->之后跟的是返回值类型,这里的返回值类型是一个String类型。

  1. func greet(person: String) -> String {
  2. let greeting = "Hello, " + person + "!"
  3. return greeting
  4. }
  5. print(greet(person: "Anna"))
  6. // Prints "Hello, Anna!"
  7. print(greet(person: "Brian"))
  8. // Prints "Hello, Brian!"

2. 函数的参数和返回值

在swift中函数的参数和返回值是非常具有灵活性的。你可以定义任何东西无论是一个简单的仅仅有一个未命名的参数的函数还是那种具有丰富的参数名称和不同的参数选项的复杂函数。

无参函数

  1. func sayHelloWorld() -> String {
  2. return "hello, world"
  3. }
  4. print(sayHelloWorld())
  5. // Prints "hello, world"

多输入参数

  1. func greet(person: String, alreadyGreeted: Bool) -> String {
  2. if alreadyGreeted {
  3. return greetAgain(person: person)
  4. } else {
  5. return greet(person: person)
  6. }
  7. }
  8. print(greet(person: "Tim", alreadyGreeted: true))
  9. // Prints "Hello again, Tim!"

没有返回值的函数

  1. func greet(person: String) {
  2. print("Hello, \(person)!")
  3. }
  4. greet(person: "Dave")
  5. // Prints "Hello, Dave!"

提示:严格地说,这里的greet函数确实还返回一个值,即使没有返回值定义。函数没有定义返回类型但返 回了一个void返回类型的特殊值。它是一个空的元组,可以写为()。

多返回值函数

你可以使用一个元组类型作为函数的返回类型返回一个有多个值组成的一个复合作为返回值。

  1. func minMax(array: [Int]) -> (min: Int, max: Int) {
  2. var currentMin = array[0]
  3. var currentMax = array[0]
  4. for value in array[1..<array.count] {
  5. if value < currentMin {
  6. currentMin = value
  7. } else if value > currentMax {
  8. currentMax = value
  9. }
  10. }
  11. return (currentMin, currentMax)
  12. }

可选元组返回类型

如果返回的值可能为空的,那么你可以使用可选元组返回类型,即在元组类型后面加一个?号。比如(Int, Int)? or (String, Int, Bool)?
上述的minMax(array:) 函数并没有对传入的数组做安全检查,当传入一个空数组时就明显悲剧了(触发runtime error)。为了应对这种情况,使用一个可选元组作为返回类型,当传入数组为空时返回nil即可解决问题。

  1. func minMax(array: [Int]) -> (min: Int, max: Int)? {
  2. if array.isEmpty { return nil }
  3. var currentMin = array[0]
  4. var currentMax = array[0]
  5. for value in array[1..<array.count] {
  6. if value < currentMin {
  7. currentMin = value
  8. } else if value > currentMax {
  9. currentMax = value
  10. }
  11. }
  12. return (currentMin, currentMax)
  13. }

3. 函数参数名

  1. func someFunction(firstParameterName: Int, secondParameterName: Int) {
  2. // In the function body, firstParameterName and secondParameterName
  3. // refer to the argument values for the first and second parameters.
  4. }
  5. someFunction(firstParameterName: 1, secondParameterName: 2)

和之前的版本不一样,每个函数参数都得有参数名,以便于更好的标识。

  1. func someFunction(argumentLabel parameterName: Int) {
  2. // In the function body, parameterName refers to the argument value for that parameter.
  3. }
  4. func greet(person: String, from hometown: String) -> String {
  5. return "Hello \(person)! Glad you could visit from \(hometown)."
  6. }
  7. print(greet(person: "Bill", from: "Cupertino"))
  8. // Prints "Hello Bill! Glad you could visit from Cupertino."
  1. func someFunction(_ firstParameterName: Int, secondParameterName: Int) {
  2. // In the function body, firstParameterName and secondParameterName
  3. // refer to the argument values for the first and second parameters.
  4. }
  5. someFunction(1, secondParameterName: 2)
  1. func someFunction(parameterWithoutDefault: Int, parameterWithDefault: Int = 12) {
  2. // If you omit the second argument when calling this function, then
  3. // the value of parameterWithDefault is 12 inside the function body.
  4. }
  5. someFunction(parameterWithoutDefault: 3, parameterWithDefault: 6) // parameterWithDefault is 6
  6. someFunction(parameterWithoutDefault: 4) // parameterWithDefault is 12

提示:函数可以最多有一个可变参数的参数,而且它必须出现在参数列表的最后以避免多参数函 数调用时出现歧义。如果函数有一个或多个参数使用默认值,并且还具有可变参数,将可变参数放在列表的 最末尾的所有默认值的参数之后。

  1. func arithmeticMean(_ numbers: Double...) -> Double {
  2. var total: Double = 0
  3. for number in numbers {
  4. total += number
  5. }
  6. return total / Double(numbers.count)
  7. }
  8. arithmeticMean(1, 2, 3, 4, 5)
  9. // returns 3.0, which is the arithmetic mean of these five numbers
  10. arithmeticMean(3, 8.25, 18.75)
  11. // returns 10.0, which is the arithmetic mean of these three numbers
  1. var someInt = 3
  2. var anotherInt = 107
  3. swapTwoInts(&someInt, &anotherInt)
  4. print("someInt is now \(someInt), and anotherInt is now \(anotherInt)")
  5. // Prints "someInt is now 107, and anotherInt is now 3"

注意:inout参数不能有默认值,并且可变参数不可以声明为inout.

4. 函数类型

每一个函数都有特定的函数类型,可以充当参数类型和函数的返回类型。例如:

  1. func addTwoInts(a: Int, b: Int) -> Int {
  2. return a + b
  3. }
  4. func multiplyTwoInts(a: Int, b: Int) -> Int {
  5. return a * b
  6. }

这个例子中定义了两个简单的数学函数addTwoInts和multiplyTwoInts。每个函数接受两个int值,并返回一个int值,执行适当的数学运算并返回结果。

这两个函数的类型是(Int, Int)->Int。可以解读为:"这个函数类型,它有两个int型的参数,并返回一个int类型的值。"

下面是另一个例子,不带任何参数或返回值的函数:

  1. func printHelloWorld() {
  2. println("hello, world")
  3. }

这个函数的类型是()->(),或者"函数没有参数,并返回void。"函数不显式的指出一个返回值类型是void,在swift中相当于一个空元组,显示为()。

在swift中您可以像任何其他类型一样的使用函数类型。例如,你可以定义一个常量或变量为一个函数类型,并指定适当的函数给该变量:

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

该addTwoInts函数具有与mathFunction相同类型的变量,所以这个赋值在能通过swift的类型检查。

现在你可以调用指定的函数名称为mathFunction:

  1. print("Result: \(mathFunction(2, 3))")
  2. // prints "Result: 5"

您可以使用一个函数类型,如(Int, Int)->Int作为另一个函数的参数类型。这使你预留了一个函数的某些方面的函数实现,让调用者提供的函数时被调用。

下面就以打印上面的数学函数的结果为例:

  1. func printMathResult(mathFunction: (Int, Int) -> Int, a: Int, b: Int) {
  2. print("Result: \(mathFunction(a, b))")
  3. }
  4. printMathResult(addTwoInts, 3, 5)
  5. // prints "Result: 8"

这个例子中定义了一个名为printMathResult函数,它有三个参数。第一个参数名为mathFunction,类型为(Int, Int)->Int。您可以传入符合的任何函数类型作为此函数的第一个参数。第二和第三个参数a、b都是int类型。被用作用于提供数学函数的两个输入值。

您可以使用一个函数类型作为另一个函数的返回类型。返回的函数-(>)即你的返回箭头后,立即写一个完整的函数类型就做到这一点。

下面的例子定义了两个简单的函数调用stepForward和stepBackward。该stepForward函数返回一个值高于其输入值,而stepBackward函数返回一个值低于其输入值。这两个函数都有一个相同的类型 (Int) -> Int:

  1. func stepForward(input: Int) -> Int {
  2. return input + 1
  3. }
  4. func stepBackward(input: Int) -> Int {
  5. return input - 1
  6. }

这里有一个chooseStepFunction函数,它的返回类型是"函数类型(Int) -> Int"。chooseStepFunction返回一个基于布尔参数的stepBackward或stepForward函数类型:

  1. func chooseStepFunction(backwards: Bool) -> (Int) -> Int {
  2. return backwards ? stepBackward : stepForward
  3. }

您现在可以使用chooseStepFunction获取一个函数,可能是加一函数或另一个:

  1. var currentValue = 3
  2. let moveNearerToZero = chooseStepFunction(currentValue > 0)
  3. // moveNearerToZero now refers to the stepBackward() function

前面的例子可以判断正负的步骤决定是否需要移动一个名为使得currentValue变量逐步接近零。currentValue初始值是3,这意味着当前值>0,则返回true,chooseStepFunction返回stepBackward函数。返回函数的引用存储在一个称为moveNearerToZero常量里。
如今moveNearerToZero执行了正确的功能,就可以用来计数到零:

  1. print("Counting to zero:")
  2. // Counting to zero:
  3. while currentValue != 0 {
  4. print("\(currentValue)... ")
  5. currentValue = moveNearerToZero(currentValue)
  6. }
  7. println("zero!")
  8. // 3...
  9. // 2...
  10. // 1...
  11. // zero!

5. 嵌套函数

迄今为止所有你在本章中遇到函数都是全局函数,在全局范围内定义。其实你还可以在其他函数中定义函数,被称为嵌套函数。

嵌套函数默认对外界是隐藏的,但仍然可以调用和使用其内部的函数。内部函数也可以返回一个嵌套函数,允许在嵌套函数内的另一个范围内使用。

你可以重写上面的chooseStepFunction例子使用并返回嵌套函数:

  1. func chooseStepFunction(backward: Bool) -> (Int) -> Int {
  2. func stepForward(input: Int) -> Int { return input + 1 }
  3. func stepBackward(input: Int) -> Int { return input - 1 }
  4. return backward ? stepBackward : stepForward
  5. }
  6. var currentValue = -4
  7. let moveNearerToZero = chooseStepFunction(backward: currentValue > 0)
  8. // moveNearerToZero now refers to the nested stepForward() function
  9. while currentValue != 0 {
  10. print("\(currentValue)... ")
  11. currentValue = moveNearerToZero(currentValue)
  12. }
  13. print("zero!")
  14. // -4...
  15. // -3...
  16. // -2...
  17. // -1...
  18. // zero!

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注