版本記錄
版本號 | 時間 |
---|---|
V1.0 | 2017.07.27 |
前言
我是swift2.0的時候開始接觸的,記得那時候還不是很穩定,公司的項目也都是用oc做的,并不對swift很重視,我自己學了一段時間,到現在swift3.0+已經出來了,自己平時也不寫,忘記的也差不多了,正好項目這段時間已經上線了,不是很忙,我就可以每天總結一點了,希望對自己對大家有所幫助。在總結的時候我會對比oc進行說明,有代碼的我會給出相關比對代碼。
1. swift簡單總結(一)—— 數據簡單值和類型轉換
2. swift簡單總結(二)—— 簡單值和控制流
3. swift簡單總結(三)—— 循環控制和函數
4. swift簡單總結(四)—— 函數和類
5. swift簡單總結(五)—— 枚舉和結構體
6. swift簡單總結(六)—— 協議擴展與泛型
7. swift簡單總結(七)—— 數據類型
8. swift簡單總結(八)—— 別名、布爾值與元組
9. swift簡單總結(九)—— 可選值和斷言
10. swift簡單總結(十)—— 運算符
11. swift簡單總結(十一)—— 字符串和字符
12. swift簡單總結(十二)—— 集合類型之數組
13. swift簡單總結(十三)—— 集合類型之字典
14. swift簡單總結(十四)—— 控制流
15. swift簡單總結(十五)—— 控制轉移語句
函數 - Functions
函數是swift
的重點,函數用來完成特定任務的獨立的代碼塊,可以給一個函數起一個名字,當函數執行的時候,這個名字就會被“調用”。swift
的函數風格很靈活,可以像C
風格的參數,也可以像OC
風格的參數,參數可以提供默認值,簡化函數調用,參數也可以既當做傳入參數,也可以當做傳出參數,也可以說,一旦函數執行結束,傳入的參數值可以被修改。
在swift
中,每個函數都有一個類型,包括函數的參數值類型和返回值類型,你可以把函數類型當做任何其他普通變量類型一樣處理,這樣可以簡單的把函數當做別的函數的參數,也可以從其他函數中返回函數,函數的定義可以寫在其他函數定義中,這樣可以在嵌套函數范圍內實現功能封裝。
下面主要講下面幾個大問題:
- 函數的定義與調用
(Defining and Calling Functions)
- 函數參數與返回值
(Function Parameters and Return Values)
- 函數參數名稱
(Function Parameter Names)
- 函數類型
(Function Types)
- 函數嵌套
(Nested Functions)
函數定義與調用 - Defining and Calling Functions
定義一個函數時,可以定義一個或者多個有名稱和類型的值,作為函數的輸入,也可以定義一種類型的值作為函數執行結束的輸出。每一個函數都有一個名字,用來描述執行的任務,可以通過函數的名字調用函數。
下面我們就看一個簡單的例子。
class JJSwiftVC: UIViewController
{
override func viewDidLoad()
{
super.viewDidLoad()
view.backgroundColor = UIColor.lightGray
print(greeting(personName: "Nana"))
}
func greeting(personName : String) -> String {
return "Hello," + personName + "!"
}
}
下面看輸出結果
Hello,Nana!
函數參數與返回值 - Function Parameters and Return Values
swift
可以有任意類型任意個數的參數,函數也可以作為參數傳入,同時,swift
可以有任意類型的返回值,函數也可以作為返回值,也可以沒有返回值,總之,非常靈活。
1. 多重輸入參數 - Multiple Input Parameters
函數可以有多個輸入參數,寫在圓括號中,用逗號分隔。
下面看一個簡單的程序。
class JJSwiftVC: UIViewController
{
override func viewDidLoad()
{
super.viewDidLoad()
view.backgroundColor = UIColor.lightGray
print(calculateDistance(start: 1, end: 100))
}
func calculateDistance(start : Int, end : Int) -> Int {
return end - start
}
}
下面看一下輸出結果
99
2. 無參函數 - Functions Without Parameters
函數可以沒有參數,這時候的函數名稱后面的圓括號里面就是空的。
class JJSwiftVC: UIViewController
{
override func viewDidLoad()
{
super.viewDidLoad()
view.backgroundColor = UIColor.lightGray
print(greeting())
}
func greeting() -> String {
return "Hello!"
}
}
下面看輸出結果
Hello!
3. 無返回值函數 - Functions Without Return Values
函數可以沒有返回值,看下面的例子,相當于OC
中返回類型為void
的方法。
class JJSwiftVC: UIViewController
{
override func viewDidLoad()
{
super.viewDidLoad()
view.backgroundColor = UIColor.lightGray
greeting(greet: "Nancy")
}
func greeting(greet : String) {
print("Hello, " + greet)
}
}
下面看輸出結果
Hello, Nancy
注意:嚴格講,雖然沒有返回值被定義,greeting
函數依然返回了值,沒有定義返回類型的函數會返回特殊的值,叫Void
,它其實是一個空的元組(tuple)
,沒有任何元素,可以寫成()
。函數就算有返回值也可以忽略不用,但是有返回值的函數必須返回一個值。
4. 多重返回值函數 - Functions with Multiple Return Values
可以使用元組tuple
類型讓多個值作為一個復合值從函數中返回,下面看一個簡單例子。
class JJSwiftVC: UIViewController
{
override func viewDidLoad()
{
super.viewDidLoad()
view.backgroundColor = UIColor.lightGray
let number = count(string: "swift is very interesting !")
print(number.vowels)
print(number.consonants)
print(number.others)
}
func count(string : String) ->(vowels : Int, consonants : Int, others : Int) {
var vowels = 0, consonants = 0, others = 0
for character in string.characters {
switch String(character).lowercased() {
case "a", "e", "i", "o", "u":
vowels += 1
case "b", "c", "d", "f", "g","h", "j", "k", "l", "m", "n", "p", "q", "r", "s", "t", "v", "w", "x", "y", "z":
consonants += 1
default:
others += 1
}
}
return(vowels, consonants, others)
}
}
下面看輸出結果
7
15
5
函數參數名稱 - Function Parameter Names
函數的參數一般都這么定義:參數名(parameter name)
這些參數只能在函數體內部使用,不能在調用函數時使用,這種類型的參數名稱被稱為局部參數名(local parameter)
。
1. 外部參數名 - External Parameter Names
有時候,調用函數時,給每個參數命名是非常有用的,因為這些參數名可以指出各個實參的用途,如果你希望函數的使用者在調用函數時提供參數名字,那就需要給每個參數除了局部參數名外再定義一個外部參數名
,外部參數名寫在局部參數名之前,用空格分開。還有幾點要注意:
- 如果你提供了外部參數名,那么函數被調用時,必須使用外部參數名。
- 當其他人讀你的代碼,函數參數意圖不是很明顯時,考慮使用外部參數名,如果函數參數名的意圖很清晰就不需要定義外部參數了。
下面看一個簡單代碼。
class JJSwiftVC: UIViewController
{
override func viewDidLoad()
{
super.viewDidLoad()
view.backgroundColor = UIColor.lightGray
print(join(string: "Hello", toString: "world", withJoiner: "-"))
}
func join(string s1 : String, toString s2 : String, withJoiner joiner : String) -> String{
return s1 + joiner + s2
}
}
下面看輸出結果
Hello-world
2. 簡寫外部參數名 - shorthand External Parameter Names
如果你需要提供外部參數名,但是局部參數名已經寫好了,那么不用再修改了,你可以只寫一次參數名,并用#
作為前綴,就表明這個參數可以作為局部參數名和外部參數名。
注意:上面是swift 3.0
以前的功能,3.0以后已經被去掉了,這里還加上這個選項,是讓大家區別一下。
3. 默認參數值 - Default Parameter Values
你可以在函數體內為每個參數定義默認值,默認值被定義后,調用這個函數時可以忽略這個參數。下面看這個簡單例子。
class JJSwiftVC: UIViewController
{
override func viewDidLoad()
{
super.viewDidLoad()
view.backgroundColor = UIColor.lightGray
print(join(string: "Hello", toString: "World", withJoiner: "-"))
print(join(string: "Hello", toString: "World"))
}
func join(string s1 : String, toString s2 : String, withJoiner joiner : String = "&&") -> String{
return s1 + joiner + s2
}
}
下面看輸出結果
Hello-World
Hello&&World
可以發現:
- 如果參數有默認值,調用如果傳值就用我們傳入的值,但是如果調用不傳值就用參數的默認值。
- 將帶有默認值的參數放在函數參數列表的最后面,這樣可以保證函數調用時候,非默認參數的順序是一致的,同時可以清晰的看見相同的函數在不同情況下調用時顯的更為清晰。
4. 默認值參數的外部參數名- External Names for Parameters with Default
當你沒有給帶默認值的參數提供外部參數名時,swift
會自動提供外部名字,函數調用的時候,外部參數名必須使用。下面看例子。
class JJSwiftVC: UIViewController
{
override func viewDidLoad()
{
super.viewDidLoad()
view.backgroundColor = UIColor.lightGray
print(join(string: "Hello", toString: "World", withJoiner: " - "))
}
func join(string : String, toString : String, withJoiner : String = "&&") -> String{
return string + withJoiner + toString
}
}
下面看輸出結果
Hello - World
注意:你也可以使用下劃線_
作為默認值參數的外部參數名,這樣可以在調用時不用提供外部參數名,但是給帶默認值參數命名總是更加合適的。
5. 可變參數 - Variadic Parameters
一個可變參數可以接受一個或多個值,函數調用時,你可以用可變參數來傳入不確定數量的輸入參數,通過在變量類型后面加上...
的方式定義可變參數。
下面我們看一個例子。
class JJSwiftVC: UIViewController
{
override func viewDidLoad()
{
super.viewDidLoad()
view.backgroundColor = UIColor.lightGray
print(sum(numbers: 1, 3, 4))
print(sum(numbers: 100, 300, 500))
}
func sum(numbers : Double...) -> Double{
var total = 0.0
for number in numbers {
total += number
}
return total
}
}
下面看輸出結果
8.0
900.0
還有幾點要注意:
- 傳入函數的參數被當做這個類型的一個數組處理。
- 一個函數最多只能有一個可變參數,而且它必須是參數表中最后的一個,這樣做的目的是為了避免函數調用出現歧義。
- 如果一個函數有一個或者多個帶默認值的參數,而且還有一個可變參數,那么把可變參數放在參數表的最后。
6. 常量參數和變量參數 - Constant and Variable Parameter
函數參數默認是常量,在函數體內改變參數值會報錯,但是有的時候有傳入參數的變量值副本是很有用的,你可以通過指定一個或者多個參數為變量函數,從而避免自己在函數中定義新的變量,變量參數不是常量,你可以在函數體內部把它當做新的可修改副本來使用。
常量參數變為變量參數的方法就是在參數名前面加關鍵字var
,說了這么多上面都是swift 3.0
以前的寫法,那么swift 3.0
以后怎么寫呢,看下面的例子。
class JJSwiftVC: UIViewController
{
override func viewDidLoad()
{
super.viewDidLoad()
view.backgroundColor = UIColor.lightGray
var number = 10
print(sum(number: &number, number2: 20))
}
func sum(number : inout Int, number2 : Int) -> Int {
number += number2
return number
}
}
下面看輸出結果
30
可以看見,現在不用var
而是用inout
了,這里需要注意的就是inout
的位置。
7. 輸入輸出函數 - InOut Parameters
有的時候我們想要一個函數可以修改參數的值,并且當函數調用結束后,這個參數仍可用,這個時候我們就要把這個參數定義為輸入輸出參數- In - Out Parameters
。定義輸入輸出參數,需要在參數定義前加一個inout
關鍵字,一個輸入輸出參數有傳入函數的值,這個值被函數修改,然后被傳出函數,替換原來的值。
下面看一個簡單的例子。
class JJSwiftVC: UIViewController
{
override func viewDidLoad()
{
super.viewDidLoad()
view.backgroundColor = UIColor.lightGray
var number1 = 10
var number2 = 20
swap(&number1, &number2)
print(number1)
print(number2)
}
func swapNumbers(a : inout Int, b : inout Int){
let temp = a
a = b
b = temp
}
}
下面看輸出結果
20
10
這里大家要注意inout
的位置,放在類型說明之前,冒號之后。
函數類型
每一個函數都有函數類型,由函數參數類型和返回值類型組成。例如(Int, Int) -> Int
它的意義就是:這個函數類型是,它有兩個Int
型的參數,并返回一個Int
型的值。
下面我們看幾種情況。
1. 使用函數類型 - Using Function Types
在swift
中,使用函數類型就像使用其他類型一樣,例如你可以定義一個類型為函數的常量或者變量,并將函數賦值給它。
var mathFunction = (Int, Int) -> Int = addInts
上面這個讀作:定義一個叫做mathFunction
的變量,類型是一個有兩個Int
型的參數并返回一個Int
型的值的函數,并將這個新變量指向addInts
函數。
有了這個定義,以后你可以使用mathFunction
調用被賦值的函數了,比如:
mathFunction(2, 3)
有相同類型的不同函數可以被賦值給同一個變量,就像非函數類型的變量一樣,比如:
mathFunction = multiplyTwoInts
這里multiplyTwoInts
和addInts
函數類型是相同的。
像其他數據類型一樣,當賦值一個函數給常量或者變量的時,swift
用來推斷其函數類型。
let anotherMathFunction = addInts
這里anotherMathFunction類型也被推斷為 (Int, Int) -> Int。
2. 函數類型作為參數類型 - Function Types as Parameter Types
這里函數類型作為參數類型并不傳入函數是如何實現的,它只關心這個傳入的函數類型是否正確,下面看一個簡單的例子。
class JJSwiftVC: UIViewController
{
override func viewDidLoad()
{
super.viewDidLoad()
view.backgroundColor = UIColor.lightGray
multiply(sum: sum, a: 1, b: 2)
}
func multiply(sum : (Int, Int) -> Int, a : Int, b : Int) {
let result = sum(a, b) * a * b
print("result = \(result)")
}
func sum(a : Int, b : Int) -> Int {
return a + b
}
}
下面看輸出結果
result = 6
3. 函數作為返回類型 - Functions Type as Return Types
你可以用函數類型作為另一個函數的返回類型,你需要做的是在返回箭頭->
后寫一個完整的函數類型。
可以看下面這個例子。
class JJSwiftVC: UIViewController
{
var currentValue = 10;
override func viewDidLoad()
{
super.viewDidLoad()
view.backgroundColor = UIColor.lightGray
while currentValue > 0 {
let moveToZero = chooseStepFunction(input: currentValue > 0)
var result = moveToZero(currentValue)
print(result)
currentValue -= 1
}
}
func chooseStepFunction(input : Bool) -> (Int) -> Int {
if input {
return backForward
}
else {
return stepForward
}
}
func stepForward(input : Int) -> Int {
return input + 1
}
func backForward(input : Int) -> Int {
return input - 1
}
}
下面看輸出結果
9
8
7
6
5
4
3
2
1
0
嵌套函數 - Nested Functions
前面介紹的函數都是全局函數,你也可以把函數定義在別的函數體中,這種函數叫做嵌套函數,嵌套函數對于外界來說是不可見的,但是可以被它們封閉函數(enclosing Function)
調用,一個封閉函數也可以返回它的某一個嵌套函數,使得這個函數可以在其他域中被使用。
我們接著看一個例子。
class JJSwiftVC: UIViewController
{
var currentValue = 10;
override func viewDidLoad()
{
super.viewDidLoad()
view.backgroundColor = UIColor.lightGray
while currentValue > 0 {
let moveToZero = chooseStepFunction(input: currentValue > 0)
var result = moveToZero(currentValue)
print(result)
currentValue -= 1
}
}
func chooseStepFunction(input : Bool) -> (Int) -> Int {
func stepForward(input : Int) -> Int {
return input + 1
}
func backForward(input : Int) -> Int {
return input - 1
}
if input {
return backForward
}
else {
return stepForward
}
}
}
下面看輸出結果
9
8
7
6
5
4
3
2
1
0
后記
未完,待續~~~