函數是一組特定的代碼塊,執行特定的任務。當你需要執行一個函數體時,你只需要調用函數的標示名。
在Swift中,函數是足夠強大和靈活的。你可以傳遞參數,并且在函數執行完畢時也可以返回數據。參數可以提供默認值,以簡化函數的調用。
每一個函數都是一個類型,這意味著可以你可以將函數作為參數傳遞到其他函數內,并返回一個函數。也可以將其他函數封裝到一個函數內形成嵌套函數。
## 定義和調用函數
下面代碼定義了一個sayHello的函數,這個函數接受一個String類型的參數,并返回一個String類型的數據。當你想調用這個函數時,只需調用函數名,并傳遞想要傳遞的數據。
~~~
func sayHello(personName: String) -> String {
let greeting = "Hello, " + personName + "!"
return greeting
}
print(sayHello("陽君"))
// prints "Hello, 陽君!"
~~~
## 函數的參數和返回值
在Swift中,函數的參數和返回值是非常靈活的,你可以定義任何類型的參數和返回值。
### 函數不攜帶參數
~~~
// 無參數,只有一個String類型的返回值
func sayHelloWorld() -> String {
return "hello, world"
}
print(sayHelloWorld())
// prints "hello, world"
~~~
### 函數攜帶多個參數
~~~
// 傳入兩個參數,并返回一個String類型的數據
func sayHello(personName: String, alreadyGreeted: Bool) -> String {
if alreadyGreeted {
return "Hello again, \(personName)!"
} else {
return "Hello, \(personName)!"
}
}
print(sayHello("陽君", alreadyGreeted: true))
// prints "Hello again, 陽君!"
~~~
### 函數沒有返回值
~~~
// 傳入一個String類型的數據,不返回任何數據
func sayGoodbye(personName: String) {
print("Goodbye, \(personName)!")
}
sayGoodbye("陽君") // prints "Goodbye, 陽君!"
~~~
### 函數有返回值
### 函數有一個返回值
~~~
// 返回一個Int類型的數據
func printAndCount(stringToPrint: String) -> Int {
print(stringToPrint)
return stringToPrint.characters.count
}
printAndCount("hello, world") // prints "hello, world"
~~~
### 函數有多個返回值
~~~
// 返回元組數據
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([8, -6, 2, 109, 3, 71])
print("min is \(bounds.min) and max is \(bounds.max)")
// prints "min is -6 and max is 109"
~~~
### 返回類型可選
當函數執行完畢時,會返回一定的數據。在有的情況下函數會返回nil的數據,此時只需要在聲明的函數返回類型后添加“?”。
~~~
// 返回一個元組或Nil
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([8, -6, 2, 109, 3, 71]) {
print("min is \(bounds.min) and max is \(bounds.max)")
// prints "min is -6 and max is 109"
}
~~~
## 參數名
### 指定外部參數名
在外部調用函數時,我們希望在傳遞參數的數據前有提示,這樣提升了代碼的閱讀性。如`sayHello("Bill", "Ted")` 增加外部參數名后變為`sayHello(to: "Bill", and: "Ted")`。
~~~
// 指定外部參數名to和and
func sayHello(to person: String, and anotherPerson: String) -> String {
return "Hello \(person) and \(anotherPerson)!"
}
print(sayHello(to: "Bill", and: "Ted"))
// prints "Hello Bill and Ted!"
~~~
### 省略外部參數名
在一些特有的情況下,我們并不需要外部參數名。由于swift的函數機制,除第一個外的其他參數必須攜帶外部參數名。如果你不想使用外部參數名,在聲明的時候可使用`_` 代替參數名。
~~~
// 使用_省略外面參數名,
func someFunction(firstParameterName: Int, _ secondParameterName: Int) {
}
someFunction(1, 2)
~~~
### 參數默認值
在函數內部,我們可以為參數設置默認值。如果外部不傳遞數據時,我們就使用設置的默認值。
~~~
// 設置默認值,當用戶不傳入時,使用默認值
func someFunction(parameterWithDefault: Int = 12) {
print("\(parameterWithDefault)")
}
someFunction(6) // 6
someFunction() // 12
~~~
### 可變參數
有的時候,我們只知道傳入函數的數據類型,不知道傳入函數的數據個數,這個時候我們可以使用`...`代表允許傳入未知個數的數據。
~~~
// 傳入的參數類型已知Double,個數未知
func arithmeticMean(numbers: Double...) -> Double {
var total: Double = 0
for number in numbers {
total += number
}
return total / Double(numbers.count)
}
print("\(arithmeticMean(1, 2, 3, 4, 5))") // 3.0
print("\(arithmeticMean(3, 8.25, 18.75))") // 10.0
~~~
### 常量和變量參數
在函數中,參數默認是let不可變。如果我們想讓這個數據可變,可能需要在函數內用一個var轉化。Swift鑒于這種情況,對參數做了優化,我們只需要用var聲明這個參數,在函數內就可改變它的數據。
~~~
// 默認為let常量參數,也可聲明var可變參數,在函數內直接修改
func alignRight(var string: String, totalLength: Int, pad: Character) -> String {
let amountToPad = totalLength - string.characters.count
if amountToPad < 1 {
return string
}
let padString = String(pad)
for _ in 1...amountToPad {
string = padString + string
}
return string
}
let originalString = "hello"
let paddedString = alignRight(originalString, totalLength: 10, pad: "-")
print("originalString:\(originalString); paddedString:\(paddedString);")
// originalString:hello; paddedString:-----hello;
~~~
### In-Out參數
當我們使用var讓參數可變的時候,往往會思考我們改變這個參數的數據,是否會改變外部的數據呢?當你改變var聲明的數據時,外面數據是不會發生任何改變的。但是有的情況,我們又希望外部數據也會跟著變化,此時我們只需要使用inout聲明這個參數。
~~~
// 使用inout聲明的參數,在函數內修改參數值時,外面參數值也會變
func swapTwoInts(inout a: Int, inout _ b: Int) {
let temporaryA = a
a = b
b = temporaryA
}
var someInt = 3
var anotherInt = 107
swapTwoInts(&someInt, &anotherInt)
print("someInt is now \(someInt), and anotherInt is now \(anotherInt)")
// prints "someInt is now 107, and anotherInt is now 3"
~~~
## 函數類型
所有的函數都是一個類型,只是這個類型有點特殊,它攜帶參數和返回值。也就意味著,你可以將一個函數用一個let或var聲明的屬性代替。當我們調用這個函數時,只需要調用這個聲明的屬性。
### 使用函數類型
~~~
// 加法
func addTwoInts(a: Int, _ b: Int) -> Int {
return a + b
}
// 乘法
func multiplyTwoInts(a: Int, _ b: Int) -> Int {
return a * b
}
// 函數體賦值為參數
var mathFunction: (Int, Int) -> Int = addTwoInts
print("Result: \(mathFunction(2, 3))") // prints "Result: 5"
// 函數體指向替換
mathFunction = multiplyTwoInts
print("Result: \(mathFunction(2, 3))") // prints "Result: 6"
// 函數體傳遞
let anotherMathFunction = addTwoInts //
// anotherMathFunction is inferred to be of type (Int, Int) -> Int
print("\(anotherMathFunction)")
~~~
### 函數做參數
下面的例子介紹了怎么將一個函數作為一個參數傳遞到另一個函數內
~~~
// 加法
func addTwoInts(a: Int, _ b: Int) -> Int {
return a + b
}
// 其中一個參數為一個函數體
func printMathResult(mathFunction: (Int, Int) -> Int, _ a: Int, _ b: Int) {
print("Result: \(mathFunction(a, b))")
}
printMathResult(addTwoInts, 3, 5) // prints "Result: 8"
~~~
### 函數做返回值
函數作為函數的參數傳遞,也就意味著函數可以作為函數的返回值。
~~~
// 加1
func stepForward(input: Int) -> Int {
return input + 1
}
// 減1
func stepBackward(input: Int) -> Int {
return input - 1
}
// 使用函數體做返回類型
func chooseStepFunction(backwards: Bool) -> (Int) -> Int {
return backwards ? stepBackward : stepForward
}
var currentValue = 3
// 此時moveNearerToZero指向stepForward函數
let moveNearerToZero = chooseStepFunction(currentValue > 0)
// 調用函數體
currentValue = moveNearerToZero(currentValue)
print("\(currentValue)... ") // prints “2...”
~~~
## 嵌套函數
本章介紹的函數體都是全局函數的例子,它被定義在全局作用域中。您也可以在一個函數體內再定義一個函數,稱為嵌套函數。
嵌套函數默認情況下是隱藏的,但你仍然可以調用和使用嵌套函數外的數據。
~~~
// 函數體內部嵌套函數,并做返回類型
func chooseStepFunction(backwards: Bool) -> (Int) -> Int {
// 嵌套函數1
func stepForward(input: Int) -> Int {
return input + 1
}
// 嵌套函數2
func stepBackward(input: Int) -> Int {
return input - 1
}
return backwards ? stepBackward : stepForward
}
var currentValue = -2
let moveNearerToZero = chooseStepFunction(currentValue > 0)
currentValue = moveNearerToZero(currentValue)
print("\(currentValue)... ") // prints "-1..."
~~~
## 其他
### 參考資料
[The Swift Programming Language (Swift 2.1)](https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/ErrorHandling.html)
### 文檔修改記錄
| 時間 | 描述 |
|-----|-----|
| 2015-10-27 | 根據 [The Swift Programming Language (Swift 2.1)](https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/ErrorHandling.html)總結 |
版權所有:[http://blog.csdn.net/y550918116j](http://blog.csdn.net/y550918116j)
- 前言
- Swift函數
- Swift閉包(Closures)
- Swift枚舉(Enumerations)
- Swift類和結構體(Classes and Structures)
- Swift屬性(Properties)
- Swift方法(Methods)
- Swift下標(Subscripts)
- Swift繼承(Inheritance)
- Swift初始化(Initialization)
- Swift銷毀(Deinitialization)
- Swift可選鏈(Optional Chaining)
- Swift錯誤處理(Error Handling)
- Swift類型選擇(Type Casting)
- Swift協議(Protocols)
- Swift訪問控制(Access Control)
- Swift高級運算符(Advanced Operators)