<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                # Swift 閉包 > 原文: [https://www.programiz.com/swift-programming/closures](https://www.programiz.com/swift-programming/closures) #### 在本文中,您將通過示例學習什么是閉包,語法,Swift 中的閉包類型。 在文章 [Swift 函數](/swift-programming/functions "Swift functions")中,我們使用`func`關鍵字創建了一個函數。 但是,Swift 中還有另一種特殊類型的函數,稱為**閉包**,可以在不使用關鍵字`func`和函數名的情況下進行定義。 像函數一樣,閉包可以接受參數并返回值。 它還包含一組語句,這些語句在調用后執行,并且可以作為函數分配給變量/常量。 閉包主要用于兩個原因: 1. **完成塊** 閉包可幫助您在某些任務完成執行時得到通知。 請參閱[閉包作為完成處理器](#completion),以了解有關它的更多信息。 2. **高階函數** 閉包可以作為高階函數的輸入參數傳遞。 高階函數只是一種接受函數作為輸入并返回類型函數的值作為輸出的函數類型。 為此,最好使用閉包代替函數,因為閉包省略了`func`關鍵字和函數名,從而使代碼更具可讀性和簡短性。 * * * ## 閉包語法 閉包表達式語法具有以下一般形式: ```swift { (parameters) -> return type in statements } ``` 請注意,在返回類型之后使用`in`關鍵字。`in`關鍵字用于在閉包內部分隔返回類型和語句。 閉包接受參數并可以返回值。 讓我們通過以下示例學習創建自己的閉包: * * * ### 示例 1:簡單閉包 ```swift let simpleClosure = { } simpleClosure() ``` 在以上語法中,我們聲明了一個簡單的閉包`{ }`,該閉包不包含任何參數,不包含任何語句且不返回任何值。 該閉包分配給常量`simpleClosure`。 我們將閉包稱為`simpleClosure()`,但是由于它不包含任何語句,因此該程序不執行任何操作。 * * * ### 示例 2:包含語句的閉包 ```swift let simpleClosure = { print("Hello, World!") } simpleClosure() ``` 當您運行上述程序時,輸出將是: ```swift Hello, World! ``` 在上面的程序中,您已經定義了一個閉包`simpleClosure`。`simpleClosure`的類型被推斷為`() -> ()`,因為它不接受參數并且不返回值。 如果要顯式定義閉包的類型,則可以使用`let simpleClosure:() -> ()`進行定義。 與第一個示例不同,以`simpleClosure()`調用閉包將在其中執行`print()`語句。 這會在控制臺中打印`Hello, World!`。 * * * ### 示例 3:接受參數的閉包 ```swift let simpleClosure:(String) -> () = { name in print(name) } simpleClosure("Hello, World") ``` 運行該程序時,輸出為: ```swift Hello, World! ``` 在上述程序中,閉包的類型`(String) -> ()`聲明閉包接受的類型為`String`,但不返回值。您可以通過在閉包的語句中放置參數`name`,后跟`in`關鍵字來使用傳遞的值。 請記住,`in`關鍵字的使用是將參數名稱與語句分開。 由于閉包接受`String`,因此在將閉包稱為`simpleClosure("Hello, World")`時需要傳遞字符串。 這將在閉包內部執行語句并輸出`"Hello, World"`。 * * * ### 示例 4:返回值的閉包 閉包也可以作為函數返回值。 如果需要從閉包中返回值,則必須顯式添加類型以返回括號內的`()`,然后是`->`。 ```swift let simpleClosure:(String) -> (String) = { name in let greeting = "Hello, World! " + "Program" return greeting } let result = simpleClosure("Hello, World") print(result) ``` 運行該程序時,輸出為: ```swift Hello, World! Program ``` 在上面的程序中,我們將類型定義為`simpleClosure: (String) -> (String)`,因為 Swift 無法自動推斷出返回值的閉包。 類型`(String) -> (String)`聲明閉包采用類型`String`的輸入,并返回類型`String`的值。 正如我們在 *Swift 函數*中了解到的那樣,閉包還使用`return`關鍵字`return greeting`返回一個值,并且返回值可以在變量/常量中分配為`let result =`。 * * * ### 示例 4:將閉包作為函數參數傳遞 我們還可以將閉包作為參數傳遞給函數,如下所示: ```swift func someSimpleFunction(someClosure:()->()) { print("Function Called") } someSimpleFunction(someClosure: { print("Hello World! from closure") }) ``` 運行該程序時,輸出為: ```swift Function Called ``` 在上述程序中,該函數接受類型為`()->()`的閉包,即不接受任何輸入且不返回任何值。 現在,當調用函數`someSimpleFunction()`時,您可以將閉包`{ print("Hello World! from closure") }`作為參數傳遞。 函數調用觸發函數內部的`print("Function Called")`語句,該語句在屏幕上輸出`Function Called`。 但是,由于尚未調用閉包,因此不會執行閉包語句。 您可以簡單地以`someClosure()`的形式調用閉包,它在閉包內執行語句。 ```swift func someSimpleFunction(someClosure:()->()) { print("Function Called") someClosure() } someSimpleFunction(someClosure: { print("Hello World! from closure") }) ``` 運行該程序時,輸出為: ```swift Function Called Hello World! from closure ``` * * * ## 尾隨閉包 如果函數接受閉包作為最后一個參數,則可以類似于`{ }`之間的函數主體傳遞閉包。 這種寫在函數調用括號之外的閉包類型稱為尾隨閉包。 可以使用結尾閉包將上述程序重寫為: ### 示例 5:尾隨閉包 ```swift func someSimpleFunction(msg:String, someClosure:()->()) { print(msg) someClosure() } someSimpleFunction(msg:"Hello Swift Community!") { print("Hello World! from closure") } ``` 運行該程序時,輸出為: ```swift Hello Swift Community! Hello World! from closure ``` 在上述程序中,函數`someSimpleFunction()`接受閉包作為最終參數。 因此,在調用函數時,沒有使用閉包作為參數,而是使用了尾隨閉包。 如您所見,在函數調用中 ```swift someSimpleFunction(msg:"Hello Swift Community!") { print("Hello World! from closure") } ``` 閉包`{ print("Hello World! from closure") }`看起來像函數的主體,而不是函數的參數,但請記住,它仍然是函數的參數。 由于尾隨閉包,我們沒有為閉包指定參數名稱,這會使代碼更短,更易讀。 寫尾隨閉包不是強制性的。 但是,出于可讀性考慮,建議當函數接受閉包作為最終參數時。 * * * ## 自動閉包 用`@autoclosure`關鍵字標記的閉包稱為自動閉包。`@autoclosure`關鍵字通過添加`{}`在表達式周圍創建自動閉包。 因此,在將閉包傳遞給函數時,可以省略花括號`{}`。 使用自動閉包的主要優點是,調用閉包時,無需將表達式用大括號`{}`括起來。 讓我們在示例中看一下。 ### 示例 6:不使用`@autoclosure`的閉包 ```swift func someSimpleFunction(someClosure:()->(), msg:String) { print(msg) someClosure() } someSimpleFunction(someClosure: ({ print("Hello World! from closure") }), msg:"Hello Swift Community!") ``` 運行該程序時,輸出為: ```swift Hello Swift Community! Hello World! from closure ``` 在上面的程序中,我們聲明了一個函數,該函數接受常規閉包`()->()`作為函數`someSimpleFunction()`的參數。 您可以看到,調用函數時,需要在函數參數周圍添加`{}`,如下所示: ```swift someClosure: ({ print("Hello World! from closure") }) ``` 我們可以使用自動閉包函數將上述程序重寫為: * * * ### 示例 7:自動閉包 ```swift func someSimpleFunction(someClosure: @autoclosure ()->(), msg:String) { print(msg) someClosure() } someSimpleFunction(someClosure: (print("Hello World! from closure")), msg:"Hello Swift Community!") ``` 運行該程序時,輸出為: ```swift Hello Swift Community! Hello World! from closure ``` 在上面的程序中,我們已將閉包`()->()`標記為具有`@autoclosure`屬性的自動閉包類型。 因此,您不必在函數參數周圍將`{ }`添加為`someClosure: (print("Hello World! from closure"))`。 * * * ## 具有參數和返回值的自動閉包 像普通的閉包一樣,您可以將參數傳遞給自動閉包并從中返回值。 但是,即使您傳遞參數,它們也會被忽略并且不能在閉包內部使用。 這是因為您無法定義參數以將其用作`{ arg in }`。 因此,建議創建不帶參數但可以返回值的自動閉包。 值是包裝在其中的表達式。 讓我們在下面的示例中看到這一點。 ### 示例 8:具有返回值的自動閉包 ```swift func someSimpleFunction(_ someClosure:@autoclosure ()->(String)) { let res = someClosure() print(res) } someSimpleFunction("Good Morning") ``` 運行該程序時,輸出為: ```swift Good Morning ``` 在上面的程序中,我們定義了一個不帶參數但返回`String`(`()->(String)`)的函數。 我們將自動閉包函數`Good Morning`傳遞給了該函數。 這也是閉包的返回值。 因此,當我們在函數內部調用`someClosure()`時,它返回了`Good Morning`值。 ### 示例 9:帶參數的自動閉包 ```swift func someSimpleFunction(_ someClosure:@autoclosure (String)->(String)) { let res = someClosure("Hello World") print(res) } someSimpleFunction("Good Morning") ``` 運行該程序時,輸出為: ```swift Good Morning ``` 在上面的程序中,我們定義了一個需要自動閉包的函數。 閉包采用`String`類型的值,并且還返回`String`類型的值。 像前面的示例一樣,我們將自動閉包`Good Morning`傳遞給函數,這是閉包的返回值。 因此,即使自動閉包稱為`someClosure("Hello World")`,它也不能接受任何參數,它仍會返回并打印`Good Morning`。 * * * ## 逃逸與無逃逸閉包 ### 無逃逸閉包 當閉包作為參數傳遞給函數時,閉包被認為是無法逃脫的,并在函數返回之前被調用。 閉包不在函數外部使用。 在 Swift 中,默認情況下所有閉包參數都不會逃逸。 逃逸和不逃逸閉包的概念是用于編譯器優化的。 #### 示例 10:無逃逸的閉包 ```swift func testFunctionWithNoEscapingClosure(myClosure:() -> Void) { print("function called") myClosure() return } //function call testFunctionWithNoEscapingClosure { print("closure called") } ``` 運行該程序時,輸出為: ```swift function called closure called ``` 在上面的示例中,閉包被稱為沒有逃逸,因為閉包`myClosure()`在函數返回之前被調用,并且閉包不在函數主體之外使用。 * * * ### 逃逸閉包 當閉包作為函數的參數傳遞給閉包時,閉包被認為是對函數的逃逸,但是在函數返回或在函數主體之外使用閉包后調用閉包。 #### 示例 11:逃逸閉包 ```swift var closureArr:[()->()] = [] func testFunctionWithEscapingClosure(myClosure:@escaping () -> Void) { print("function called") closureArr.append(myClosure) myClosure() return } testFunctionWithEscapingClosure { print("closure called") } ``` 運行該程序時,輸出為: ```swift function called closure called ``` 在上面的示例中,我們聲明了一個變量`ClosureArr`,它可以存儲類型為`()->()`的閉包數組。 現在,如果將在函數范圍內定義的閉包`myClosure`附加到在函數外部定義的`ClosureArr`,則閉包`myClosure`需要逸出函數主體。 因此,閉包需要逃逸并標記為`@escaping`關鍵字。 #### 示例 12:無逃逸的閉包 在上面的“不逃逸閉包”部分中,我們描述了如果在函數返回之前調用了閉包,則閉包需要不逃逸。 因此,如果在函數返回后調用閉包,則應該逃逸,對嗎? 讓我們用一個例子測試一下: ```swift func testFunctionWithNoEscapingClosure(myClosure:() -> Void) { return myClosure() } ``` 上面的代碼返回警告,因為出現在`return`語句之后的語句(在我們的示例中為`myClosure()`)沒有執行,因為`return`語句將程序的控制權轉移給了函數調用者。 因此,我們如何測試,以便在函數返回后調用閉包。 如果將閉包調用放在異步操作中,則可以完成此操作。 同步操作在移至下一條語句(從上到下的順序)之前等待操作完成/完成。 并且,即使當前操作尚未完成,異步也會移至下一條語句。 因此,放置在異步操作內的語句可能稍后會在某些時候執行。 ```swift func testFunctionWithNoEscapingClosure(myClosure:@escaping () -> Void) { DispatchQueue.main.async { myClosure() } return } ``` 在上述程序中,`DispatchQueue.main.async`異步運行代碼塊。 所以,現在。 即使在函數返回后也可能發生閉包調用`myClosure()`。 因此,閉包需要逃逸,并用`@escaping`關鍵字標記。 * * * ## 閉包為完成處理器 完成處理器是回調/通知,可讓您在函數完成其任務時執行某些操作。 完成處理器主要用于異步操作中,以便調用者可以知道操作何時完成,以便在操作完成后執行某些操作。 ### 示例 13:作為完成處理器的閉包 ```swift func doSomeWork(completion:()->()) { print("function called") print("some work here") print("before calling callback") completion() print("after calling callback") } doSomeWork(completion: { print("call back received") }) print("Other statements") ``` 運行該程序時,輸出為: ```swift function called some work here before calling callback call back received after calling callback Other statements ``` 上面的程序也可以使用結尾閉包重寫為: ### 示例 14:尾隨閉包作為完成處理器 ```swift func doSomeWork(completion:()->()) { print("function called") print("some work here") print("before calling callback") completion() print("after calling callback") } doSomeWork() { print("call back received") } print("Other statements") ``` * * * ### 完成處理器如何工作? ![Closure as a completion handler](https://img.kancloud.cn/72/99/729933d4a4132c54f92a14d31c4fc1da_500x308.png "Closure as a completion handler") 執行步驟如下: 1. `doSomeWork()`調用在函數內部執行語句的函數 2. `print("function called")`在控制臺中輸出`"function called"`。 3. 您可以在函數內部執行一些工作。 目前,僅`print("some work here")`語句在控制臺中的輸出為**。** 4. 對閉包的簡單調用為`completion()`,它將發送回調并將程序的控制權轉移到閉包內的語句。 因此,執行`print("call back received")`,在控制臺中輸出`"call back received"`。 5. 之后,程序控制再次返回到閉包調用,并執行語句`print("after calling callback")`,該語句在控制臺中輸出`"after calling callback"`。 6. 函數內部的語句執行后,程序將控制權轉移到函數調用`doSomeWork()`,然后執行下一個語句`print("Other statements")`,該語句在控制臺中輸出`"Other statements"`。 讓我們來看一個更實際的示例,將閉包用作完成處理器。 * * * ### 示例 11:作為完成處理器的閉包 ```swift var closeButtonPressed = false func codeinPlayground(completion:(String)->()) { print("Code, Take a Nap and Relax") if closeButtonPressed { completion("Close the playground") } } codeinPlayground { (msg) in print(msg) } ``` 運行該程序時,輸出為: ```swift Code, Take a Nap and Relax ``` 在上面的程序中,我們聲明了一個變量`closeButtonPressed`,該變量將模擬用戶是否在游樂場上輕按了閉包按鈕。 想想如果您按下閉包按鈕,變量`closeButtonPressed`將是`true`。 函數`codeinPlayground`接受閉包作為參數。 閉包`completion`接受`String`,但不返回值。 由于`closeButtonPressed`被分配了`false`,因此`if`語句內的語句未執行且沒有調用閉包。 現在,如果將`closeButtonPressed`分配給`true`(即,當用戶按下閉包按鈕時)作為`var closeButtonPressed = true`,則會調用`if`執行和閉包語句。 當為變量`closeButtonPressed`分配`true`時,輸出為: ```swift Code, Take a Nap and Relax Close the playground ``` 在這里,我們將閉包用作完成處理器,因為當用戶點擊閉包按鈕時,我們不想在函數`codeinPlayground`中執行語句,而是通過調用閉包`completion("Close the playground")`來完成其執行。 這樣,我們就有機會處理與閉包語句內的函數相關的所有最終事件。 在本例中,我們在控制臺中將消息輸出為`print(msg)`。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看