標籤:使用 strong os io for cti
函數
注意: 沒有定義傳回型別的函數會返回特殊的值,叫 Void。它其實是一個空的元組(tuple),沒有任何元素,可以寫成()。
使用元組作為返回參數,返回多個參數
func count(string: String) -> (vowels: Int, consonants: Int, others: Int) { var vowels = 0, consonants = 0, others = 0 for character in string { switch String(character).lowercaseString { case "a", "e", "i", "o", "u": ++vowels case "b", "c", "d", "f", "g", "h", "j", "k", "l", "m", "n", "p", "q", "r", "s", "t", "v", "w", "x", "y", "z": ++consonants default: ++others } } return (vowels, consonants, others)}
外部參數名
外部參數名..是為了調用該函數時讓其參數更為有表現力,更為通順,同時還保持了函數體是可讀的和有明確意圖的。讓別人閱讀整段代碼時更方便
當其他人在第一次讀你的代碼,函數參數的意圖顯得不明顯時,考慮使用外部參數名。如果函數參數名的意圖是很明顯的,那就不需要定義外部參數名了
func join(string s1: String, toString s2: String, withJoiner joiner: String) -> String { return s1 + joiner + s2 } join(string: "hello", toString: "world", withJoiner: ", ")
如果你需要提供外部參數名,但是局部參數名已經定義好了,那麼你不需要寫兩次參數名。相反,唯寫一次參數名,並用井號(#)作為首碼就可以了。這告訴 Swift 使用這個參數名作為局部和外部參數名。
func containsCharacter(#string: String, #characterToFind: Character) -> Bool { for character in string { if character == characterToFind { return true } } return false}
預設值
將帶有預設值的參數放在函數參數列表的最後。這樣可以保證在函數調用時,非預設參數的順序是一致的,同時使得相同的函數在不同情況下調用時顯得更為清晰。
當你未給帶預設值的參數提供外部參數名時,Swift 會自動提供外部名字。此時外部參數名與局部名字是一樣的,就像你已經在局部參數名前寫了井號(#)一樣。
func join(s1: String, s2: String, joiner: String = " ") -> String { return s1 + joiner + s2} join("hello", "world", joiner: "-")// returns "hello-world"
可變參數
一個可變參數(variadic parameter)可以接受一個或多個值.傳入可變參數的值在函數體內當做這個類型的一個數組。
- 一個函數至多能有一個可變參數,而且它必須是參數表中最後的一個。這樣做是為了避免函數調用時出現歧義。
- 如果函數有一個或多個帶預設值的參數,而且還有一個可變參數,那麼把可變參數放在參數表的最後。
func arithmeticMean(numbers: Double...) -> Double { var total: Double = 0 for number in numbers { total += number } return total / Double(numbers.count)}
常量參數和變數參數
函數參數預設是常量。試圖在函數體中更改參數值將會導致編譯錯誤。這意味著你不能錯誤地更改參數值
注意: 對變數參數所進行的修改在函數調用結束後便消失了,並且對於函數體外是不可見的。變數參數僅僅存在於函數調用的生命週期中。
func alignRight(var string: String, count: Int, pad: Character) -> String { let amountToPad = count - countElements(string) for _ in 1...amountToPad { string = pad + string } return string}//下面這樣會報錯func test(a:String){ a = "sssss";}
In-Out參數
- 定義一個輸入輸出參數時,在參數定義前加 inout 關鍵字
- 輸入輸出參數不能有預設值,而且可變參數不能用 inout 標記。如果你用 inout 標記一個參數,這個參數不能被 var 或者 let 標記。
- 當傳入的參數作為輸入輸出參數時,需要在參數前加&符,表示這個值可以被函數修改
func swapTwoInts(inout a: Int, inout b: Int) { let temporaryA = a a = b b = temporaryA}var someInt = 3var anotherInt = 107swapTwoInts(&someInt, &anotherInt);// "someInt is now 107, and anotherInt is now 3”
函數類型
函數類型,可以讓一個變數可以成為多個函數,同時可以把函數當參數進行傳遞或者當做傳回值
var mathFunction: (Int, Int) -> Int = addTwoIntsfunc printMathResult(mathFunction: (Int, Int) -> Int, a: Int, b: Int) { println("Result: \(mathFunction(a, b))")}func chooseStepFunction(backwards: Bool) -> (Int) -> Int { func stepForward(input: Int) -> Int { return input + 1 } func stepBackward(input: Int) -> Int { return input - 1 } return backwards ? stepBackward : stepForward}
閉包
閉包可以捕獲和儲存其所在上下文中任意常量和變數的引用。 這就是所謂的閉合并包裹著這些常量和變數,俗稱閉包。Swift 會為您管理在捕獲過程中涉及到的所有記憶體操作。
-
閉包採取如下三種形式之一:
-
全域函數是一個有名字但不會捕獲任何值的閉包
-
嵌套函數是一個有名字並可以捕獲其封閉函數域內值的閉包
-
閉包運算式是一個利用輕量級文法所寫的可以捕獲其上下文中變數或常量值的匿名閉包
閉包運算式:
{ (parameters) -> returnType in statements }
閉包特性一:利用上下文推斷參數和傳回值類型
閉包作為函數參數的話,由於類型推斷...可以省去閉包參數的類型和傳回值閉
reversed = sorted(names, { (s1: String, s2: String) -> Bool in return s1 > s2 } ) reversed = sorted(names, { s1, s2 in return s1 > s2 } )
閉包特性二:隱式返回單運算式閉包,即單運算式閉包可以省略return關鍵字
包函數體內如果是單一運算式,還可以省去return語句
reversed = sorted(names, { s1, s2 in s1 > s2 } )
閉包特性三:參數名稱縮寫
- 1 當使用參數名稱縮寫的時候可以省去in
- 2 運算子函數(Operator Functions)起作用還可以簡寫
reversed = sorted(names, { $0 > $1 } )reversed = sorted(names, >)
閉包特性四:尾隨(Trailing)閉包文法
如果您需要將一個很長的閉包運算式作為最後一個參數傳遞給函數,可以使用尾隨閉包來增強函數的可讀性。 尾隨閉包是一個書寫在函數括弧之後的閉包運算式,函數支援將其作為最後一個參數調用。
let digitNames = [ 0: "Zero", 1: "One", 2: "Two", 3: "Three", 4: "Four", 5: "Five", 6: "Six", 7: "Seven", 8: "Eight", 9: "Nine"]let numbers = [16, 58, 510]let strings = numbers.map { (var number) -> String in var output = "" while number > 0 { output = digitNames[number % 10]! + output number /= 10 } return output}
捕獲值
閉包可以在其定義的上下文中捕獲常量或變數。
即使定義這些常量和變數的原域已經不存在,閉包仍然可以在閉包函數體內引用和修改這些值。
閉包是參考型別。但是注意,當一個嵌套函數內的函數作為傳回值的時候實際上是建立了一個新的函數.
//全域函數var str = "Hello, playground"func test(a:String=""){ println(str)}test(); //"Hello, playground"str = "Hello";test(); //"Hello"//嵌套函數func makeIncrementor(forIncrement amount: Int) -> () -> Int { var runningTotal = 0 func incrementor() -> Int { runningTotal += amount //runningTotal return runningTotal } return incrementor}let incrementByTen = makeIncrementor(forIncrement: 10)incrementByTen()// 返回的值為10incrementByTen()// 返回的值為20incrementByTen()// 返回的值為30//由於是建立了一個新函數..所以會像下面顯示let incrementBySeven = makeIncrementor(forIncrement: 7)incrementBySeven()// 返回的值為7incrementByTen()// 返回的值為40//由於是參考型別.所以let alsoIncrementByTen = incrementByTenalsoIncrementByTen()// 返回的值為50
注意: Swift 會決定捕獲引用還是拷貝值。 您不需要標註amount或者runningTotal來聲明在嵌入的incrementor函數中的使用方式。 Swift 同時也處理runingTotal變數的記憶體管理操作,如果不再被incrementor函數使用,則會被清除。