swift學(xué)習(xí)筆記二

一、函數(shù)
1.swift中函數(shù)可以當(dāng)作別的函數(shù)的參數(shù),也可以從其他函數(shù)中返回
函數(shù)的定義可以寫在其他函數(shù)的定義中,可以在嵌套函數(shù)范圍內(nèi)實(shí)現(xiàn)功能的封裝

2.多重返回值函數(shù)
可以用元組類型作為一個(gè)復(fù)合值從函數(shù)中返回,元組的成員不需要再元組從函數(shù)中返回時(shí)命名

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)
}
print(minMax(array: [1, 3, 3, 5, 6]))
//打印結(jié)果 (1, 6)

上面的函數(shù)返回的元組可以時(shí)(min: Int, max: Int)? 類型

4.默認(rèn)參數(shù)
在函數(shù)體中通過給參數(shù)賦值來為任意一個(gè)參數(shù)定義默認(rèn)值,當(dāng)默認(rèn)值被定義后,調(diào)用這個(gè)函數(shù)時(shí)可以忽略這個(gè)參數(shù)。

func someFunction(parameterWithoutDefault: Int, parameterWithDefault: Int = 12) {
    print(parameterWithDefault,parameterWithoutDefault)
}
someFunction(parameterWithoutDefault: 10)
someFunction(parameterWithoutDefault: 8, parameterWithDefault: 6)

5.可變參數(shù)
一個(gè)函數(shù)最多只能擁有一個(gè)可變參數(shù),一個(gè)可變參數(shù)可以接受零個(gè)或多個(gè)值,函數(shù)調(diào)用時(shí),你可以用可變參數(shù)來制定函數(shù)參數(shù)可以被傳入不確定數(shù)量的輸入值,通過在變量類型名后面加入(...)的方式來定義可變參數(shù)

func arithmeticMean(_ numbers: Double...) -> Double {
    var total: Double = 0
    for number in numbers {
        total += number
    }
    return total / Double(numbers.count)
}
arithmeticMean(1, 2, 3, 4, 5)
// 返回 3.0, 是這 5 個(gè)數(shù)的平均數(shù)。
arithmeticMean(3, 8.25, 18.75)
// 返回 10.0, 是這 3 個(gè)數(shù)的平均數(shù)。

6.輸入輸出參數(shù)(函數(shù)參數(shù)默認(rèn)時(shí)常量,在函數(shù)體內(nèi)不能改變他的值)
輸入輸出參數(shù)不能又默認(rèn)值,而且可變參數(shù)不能用inout標(biāo)記

func swapTwoInts(_ a: inout Int, _ b: inout 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)")
// 打印 "someInt is now 107, and anotherInt is now 3"

7.函數(shù)的類型
函數(shù)的類型是由函數(shù)的參數(shù)類型和返回類型組成
(Int, Int) -> Int

8.函數(shù)類型作為參數(shù)類型

func printMathResult(_ mathFunction: (Int, Int) -> Int, _ a: Int, _b: Int) {
        print(mathFunction(a, b))
}
printMathResult(addTwoInts, 4, 6)

9.函數(shù)類型作為返回類型

func stepForward(_ input: Int) -> Int {
    return input + 1
}
func stepBackward(_ input: Int) -> Int {
    return input - 1
}
func chooseStepFunction(backward: Bool) -> (Int) -> Int {
    return backward ? stepBackward : stepForward
}
var currentValue = 3
let moveNearerToZero = chooseStepFunction(backward: currentValue > 0)
// moveNearerToZero 現(xiàn)在指向 stepBackward() 函數(shù)。
print("Counting to zero:")
// Counting to zero:
while currentValue != 0 {
    print("\(currentValue)... ")
    currentValue = moveNearerToZero(currentValue)
}
print("zero!")
// 3...
// 2...
// 1...
// zero!

10.嵌套函數(shù)
可以把函數(shù)定義在別的函數(shù)體中,默認(rèn)情況在外部是不能調(diào)用的,但是可以作為返回值返回

二、閉包
1.函數(shù)時(shí)特殊的閉包
全局函數(shù)是一個(gè)有名字但不會(huì)捕獲任何值的函數(shù)
嵌套函數(shù)是有名字并可以捕獲其封閉函數(shù)域內(nèi)值的閉包

swift的閉包表達(dá)式擁有簡(jiǎn)潔的風(fēng)格,并鼓勵(lì)在場(chǎng)景中進(jìn)行語法優(yōu)化:
利用上下文推斷參數(shù)和返回值類型
隱式表達(dá)單表達(dá)式閉包,即但表達(dá)式閉包可以隱藏return關(guān)鍵字
參數(shù)名稱縮寫
尾隨閉包語法

2.閉包表達(dá)式語法

{ (parameters) -> returnType in
        statements
}

閉包的參數(shù)可以是 in-out參數(shù),但不能設(shè)定默認(rèn)值。也可以使用具名的可變參數(shù),元組也可以作為參數(shù)和返回值

3.尾隨閉包
如果你需要將一個(gè)很長(zhǎng)的閉包表達(dá)式作為最后一個(gè)參數(shù)傳遞給函數(shù),可以使用尾隨閉包來增強(qiáng)函數(shù)的可讀性。尾隨閉包是一個(gè)書寫在函數(shù)括號(hào)之后的閉包表達(dá)式,函數(shù)支持將其作為最后一個(gè)參數(shù)調(diào)用。在使用尾隨閉包的時(shí)候,你不用寫出他的參數(shù)標(biāo)簽

func someFunctionThatTakesAClosure(closure: () -> Void) {
    // 函數(shù)體部分
}

// 以下是不使用尾隨閉包進(jìn)行函數(shù)調(diào)用
someFunctionThatTakesAClosure(closure: {
    // 閉包主體部分
})

// 以下是使用尾隨閉包進(jìn)行函數(shù)調(diào)用
someFunctionThatTakesAClosure() {
    // 閉包主體部分
}

如果閉包表達(dá)式是函數(shù)或方法的唯一參數(shù),甚至可以把函數(shù)后面的()省略

 someFunctionThatTakesAClosure{
      // 閉包主體部分
}

4.值捕獲
閉包可以在其定義的上下文中捕獲常量或者變量,即使這些常量或者變量的原作用域已經(jīng)不存在,閉包仍然可以在閉包函數(shù)體內(nèi)引用和修改這些值。

5.閉包是引用類型
函數(shù)和閉包都是引用類型

6.逃逸閉包
當(dāng)一個(gè)閉包作為一個(gè)參數(shù)傳到一個(gè)函數(shù)中,但是這個(gè)閉包在函數(shù)返回之后才能執(zhí)行,我們稱該閉包從函數(shù)中逃逸,定義此類型的閉包的時(shí)候,在閉包前面添加關(guān)鍵字@escaping,用來指明這個(gè)表是允許逃逸出這個(gè)函數(shù)的。

var completionHandlers: [() -> Void] = []
func someFunctionWithEscapingClosure(completionHandler: @escaping () -> Void) {
    completionHandlers.append(completionHandler)
}

someFunctionWithEscapingClosure(_:)函數(shù)接受一個(gè)閉包作為參數(shù),該閉包被添加到函數(shù)外定義的數(shù)組中,如果不添加@escaping 編譯就會(huì)報(bào)錯(cuò)

將一個(gè)閉包標(biāo)記為@escaping 意味著必須在閉包中顯示的引用self

func someFunctionWithNonescapingClosure(closure: () -> Void) {
    closure()
}

class SomeClass {
    var x = 10
    func doSomething() {
        someFunctionWithEscapingClosure { self.x = 100 }
        someFunctionWithNonescapingClosure { x = 200 }
    }
}

let instance = SomeClass()
instance.doSomething()
print(instance.x)
// 打印出 "200"

completionHandlers.first?()
print(instance.x)
// 打印出 "100"

7.自動(dòng)閉包
自動(dòng)閉包能讓你延遲求值,因?yàn)橹滥阏{(diào)用這個(gè)閉包,代碼段才會(huì)執(zhí)行

var customersInLine = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
print(customersInLine.count)
// 打印出 "5"

let customerProvider = { customersInLine.remove(at: 0) }
print(customersInLine.count)
// 打印出 "5"

print("Now serving \(customerProvider())!")
// Prints "Now serving Chris!"
print(customersInLine.count)
// 打印出 "4"

customerProvider的類型不是String 而是一個(gè)沒有參數(shù)返回值為String的函數(shù)

將閉包作為參數(shù)傳遞給函數(shù)

// customersInLine is ["Alex", "Ewa", "Barry", "Daniella"]
func serve(customer customerProvider: () -> String) {
    print("Now serving \(customerProvider())!")
}
serve(customer: { customersInLine.remove(at: 0) } )
// 打印出 "Now serving Alex!"

上面的 serve(customer:)
函數(shù)接受一個(gè)返回顧客名字的顯式的閉包。下面這個(gè)版本的 serve(customer:)完成了相同的操作,不過它并沒有接受一個(gè)顯式的閉包,而是通過將參數(shù)標(biāo)記為 @autoclosure來接收一個(gè)自動(dòng)閉包。現(xiàn)在你可以將該函數(shù)當(dāng)作接受 String 類型參數(shù)(而非閉包)的函數(shù)來調(diào)用。customerProvider參數(shù)將自動(dòng)轉(zhuǎn)化為一個(gè)閉包,因?yàn)樵搮?shù)被標(biāo)記了 @autoclosure特性。

// customersInLine is ["Ewa", "Barry", "Daniella"]
func serve(customer customerProvider: @autoclosure () -> String) {
    print("Now serving \(customerProvider())!")
}
serve(customer: customersInLine.remove(at: 0))
// 打印 "Now serving Ewa!"
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容