Swift函數
前言
Swift統一的函數語法足夠靈活,可以用來表示任何函數,包括從最簡單的沒有參數名字的 C 風格函數,到復雜的帶局部和外部參數名的Objective-C風格函數。參數可以提供默認值,以簡化函數調用。參數也可以既當做傳入參數,也當做傳出參數,也就是說,一旦函數執行結束,傳入的參數值可以被修改。
在 Swift 中,每個函數都有一種類型,包括函數的參數值類型和返回值類型。你可以把函數類型當做任何其他普通變量類型一樣處理,這樣就可以更簡單地把函數當做別的函數的參數,也可以從其他函數中返回函數。函數的定義可以寫在在其他函數定義中,這樣可以在嵌套函數范圍內實現功能封裝。
注明:Swift版本為2.1測試環境:xcode 7.2
函數定義與調用(Defining and Calling Functions)
函數定義語法為:func 函數名(參數列表) ->返回值:
// 函數定義方式:func 函數名稱(arg...) ->ReturnValue functestFunc() ->Void { // 無參數,無返回值 }
若無返回值,可以直接省略 ->Void :
functestArgFunc(arg: Int) { // 無返回值可以使用Void,其實是空元組 }
我們先來看看官方定義的 Void 是什么:
/// The empty tuple type. /// /// This is the default return type of functions for which no explicit /// return type is specified. publictypealiasVoid = ()
它其實就是一個空元組。它是作為函數無顯示指定返回類型時的默認返回值類型。
參數列表可以使用可變參數:
// 可變參數 funccalSum(array: Int...) ->Int { varsum = 0 foritemin array { sum += item } return sum }
函數調用就是通過我們的函數名稱調用:
calSum(1, 2, 3) // 6 calSum(1, 2) // 3
swift支持函數重載:
// 函數重載 funccalSum(array: [Int]) ->Int { varsum = 0 foritemin array { sum += item } return sum } // 調用方式與上面一樣,只是參數類型不一樣 calSum([1, 2, 3])// 6 calSum([1, 4, 5]) // 10
函數有多個參數時,使用逗號分開,像: (arg1: Int, arg2, Int, arg3: Int) :
funcmultipleFunc(arg1: Int, _arg2: Int) ->Int { return 0 }
多重返回值函數(Functions with Multiple Return Values)
當函數有多個返回值時,我們可以使用元組作為返回值,當然也可以使用數組、字典等,但是使用元組更簡單,更明確:
funcminMax(array: [Int]) -> (min: Int,max: Int) { varcurrentMin = array[0] var currentMax = array[0] for valuein array[1..<array.count] { if value < currentMin { currentMin = value } else if value > currentMax { currentMax = value } } return (currentMin, currentMax) }
Optional返回值類型
當函數不一定有返回值時,可以返回可選類型,在類型后面添加個問號即可:
funcminMax(array: [Int]) -> (min: Int,max: Int)? { if array.isEmpty { return nil } varcurrentMin = array[0] var currentMax = array[0] for valuein array[1..<array.count] { if value < currentMin { currentMin = value } else if value > currentMax { currentMax = value } } return (currentMin, currentMax) } // 調用的時候,通過值綁定來判斷是否有值 if letbounds = 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"
指定外部參數名(Specifying External Parameter Names)
我們看看Dictonary的一個API:
publicmutatingfuncremoveAll(keepCapacity keepCapacity: Bool = default)
我們可以看到這里一個參數有兩個名字:keepCapacity,其中第一個叫外部參數名,第二個叫函數內部變量。
比如,with是外部參數名,用于在調用時顯示的;而userId是函數內部變量名,用于內部使用:
funcfind(withuserId: Int) ->User? { } if letuser = find(with: 10) { // find }
默認參數值(Default Parameter Values)
默認參數要放在參數列表最后:
funcsomeFunction(parameterWithDefault: Int = 12) { // function body goes here // if no arguments are passed to the function call, // value of parameterWithDefault is 12 } someFunction(6) // parameterWithDefault is 6 someFunction() // parameterWithDefault is 12
可變參數(Variadic Parameters)
可變參數可以接收多個參數:
// 可變參數 // 可變參數接受0個或者多個指定類型的值。可變參數使用...表示 // 函數最多只能有一個可變參數,并且如果有可變參數,這個可變參數必須出現在參數列表的最后 // 如果參數列表中有一或多個參數提供默認值,且有可變參數,那么可變參數也要放到所有最后一個 // 提供默認值的參數之后(先是默認值參數,才能到可變參數) funcarithmeticMean(numbers: Double...) -> Double { vartotal = 0.0 fornumberin numbers { total += number } return total / Double(numbers.count) } arithmeticMean(1, 2, 3, ,4 5) // return 3.0 arithmeticMean(1, 2, 3) // return 2.0
常量參數和變量參數(Constant and Variable Parameters)
函數參數默認是常量。試圖在函數體中更改參數值將會導致編譯錯誤。這意味著你不能錯誤地更改參數值。
如果要在函數內部修改參數值,那么需要手動聲明為變量類型:
// 常量和變量參數 // 在函數參數列表中,如果沒有指定參數是常量還是變量,那么默認是let,即常量 // 這里Str需要在函數體內修改,所以需要指定為變量類型,即用關鍵字var funcalignRight(varstr: String,count: Int,pad: Character) -> String { letamountToPad = count - countElements(str) // 使用_表示忽略,因為這里沒有使用到 for _ in 1...amountToPad { str = pad + str } return str }
輸入輸出參數(In-Out Parameters)
// 輸入/輸出參數 // 有時候,在函數體內修改了參數的值,如何能直接修改原始實參呢?就是使用In-Out參數 // 使用inout關鍵字聲明的變量就是了 // 下面這種寫法,是不是很像C++中的傳引用? funcswap(inoutlhs: Int, inoutrhs: Int) { lettmp = lhs lhs = rhs rhs = tmp } // 如何調用呢?調用的調用,對應的實參前面需要添加&這個符號 // 因為需要修改,所以一定是var類型的 varfirst = 3 varsecond = 4 // 這種方式會修改實參的值 swap(&first, &second) // first = 4, second = 3
函數類型(Function Types)
// 使用函數類型 // 這里是返回Int類型 // 函數類型是:(Int, Int) -> Int funcaddTwoInts(first: Int,second: Int) -> Int { return first + second } // 函數類型是:(Int, Int) -> Int funcmultiplyTwoInts(first: Int,second: Int) -> Int { return first* second }
使用函數類型(Using Function Types)
函數類型也需要類型,也可以用于定義變量,只是它是函數指針類型變量:
var mathFunction: (Int, Int) -> Int = addTwoInts mathFunction(1, 2) // return 3 mathFunction = multiplyTwoInts mathFunction(1, 2) // return 2
函數類型作為參數類型(Function Types as Parameter Types)
函數類型也是類型,也可以作為函數的形參:
// 函數類型可以作為參數 funcprintMathResult(mathFunction: (Int, Int) -> Int,first: Int,second: Int) { println("Result: \(mathFunction(first, second))") } printMathResult(addTwoInts, 3, 5) // prints "Result: 8" printMathResult(multiplyTwoInts, 3, 5) // prints "Result: 15"
函數類型作為返回類型(Function Types as Return Types)
函數類型也可以作為返回值類型:
// 函數作為返回類型 funcstepForward(input: Int) -> Int { return input + 1 } funcstepBackward(intput: Int) -> Int { return input - 1 } funcchooseStepFunction(backwards: Bool) -> ((Int) -> Int) { return backwards ?stepBackward: stepForward } varcurrentValue = 3 letmoveNearerToZero = chooseStepFunction(currentValue > 0) // call stepBackward() function // 參數可以嵌套定義,在C、OC中是不可以嵌套的哦 funcchooseStepFunction(backwards: Bool) -> ((Int) -> Int) { funcstepForward(input: Int) -> Int { return input + 1 } funcstepBackward(input: Int) -> Int { return input + 1 } return backwards ? stepBackward : stepForward }
嵌套函數(Nested Functions)
在Ojbective-C中,函數是不能嵌套定義的,但是在swift中是可以嵌套的:
funcchooseStepFunction(backwards: Bool) -> (Int) -> Int { funcstepForward(input: Int) -> Int { return input + 1 } funcstepBackward(input: Int) -> Int { return input - 1 } return backwards ?stepBackward: stepForward } varcurrentValue = -4 letmoveNearerToZero = chooseStepFunction(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!
寫在最后
本篇博文是筆者在學習Swift 2.1的過程中記錄下來的,可能有些翻譯不到位,還請指出。另外,所有例子都是筆者練習寫的,若有不合理之處,還望指出。
學習一門語言最好的方法不是看萬遍書,而是動手操作、動手練習。如果大家喜歡,可以關注哦,盡量2-3天整理一篇Swift 2.1的文章。這里所寫的是基礎知識,如果您已經是大神,還請繞路!
關注我
如果在使用過程中遇到問題,或者想要與我交流,可加入有問必答 QQ群: 324400294
關注微信公眾號: iOSDevShares
關注新浪微博賬號:標哥Jacky
支持并捐助
如果您覺得文章對您很有幫助,希望得到您的支持。您的捐肋將會給予我最大的鼓勵,感謝您的支持!
支付寶捐助 | 微信捐助 |
---|---|
![]() |
![]() |