<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>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                閉包是自包含的功能代碼塊,可以在代碼中使用或者用來作為參數傳值。 在Swift中的閉包與C、OC中的blocks和其它編程語言(如Python)中的lambdas類似。 閉包可以捕獲和存儲上下文中定義的的任何常量和變量的引用。這就是所謂的變量和變量的自封閉, 因此命名為”閉包“(“Closures)”)。Swift還會處理所有捕獲的引用的內存管理。 全局函數和嵌套函數其實就是特殊的閉包。 閉包的形式有三種: - 全局函數都是閉包,有名字但不能捕獲任何值。 - 嵌套函數都是閉包,且有名字,也能捕獲封閉函數內的值。 - 閉包表達式都是無名閉包,使用輕量級語法,可以根據上下文環境捕獲值。 Swift中的閉包有很多優化的地方: - 根據上下文推斷參數和返回值類型; - 從單行表達式閉包中隱式返回(也就是閉包體只有一行代碼,可以省略return); - 可以使用簡化參數名,如0,1(從0開始,表示第i個參數…); - 提供了尾隨閉包語法(Trailing closure syntax)。 ## 閉包表達式 嵌套函數是非常強大的功能,在一個函數體內嵌套另一個函數。將函數作為參數和返回值也非常有用。這些都是一些特殊情況下的閉包。 閉包表達式是一種簡短的、集中的語法。閉包表達式為了縮短代碼以及優化代碼的閱讀性,提供了幾種語法優化。這里使用數組的排序為大家展示閉包的優化。 ### Sort方法 ~~~ // 函數做參數,排序 let names = ["陽君", "937447974", "a", "b", "c"] func backwards(s1: String, _ s2: String) -> Bool { return s1 > s2 } var reversed = names.sort(backwards) ~~~ 從代碼中可以看出,將函數作為參數傳遞對于代碼的閱讀性不是很好,這里就需要閉包表達式對其優化。 ### 閉包語法 閉包表達式的結構圖如下所示: ![](https://box.kancloud.cn/2016-06-01_574e9af8cd710.jpg "") - parameters:閉包接受的參數; - return type:閉包運行完畢的返回值; - statements:閉包內的運行代碼。 下面運用閉包表達式代替backwards函數對sort進行優化。 ~~~ reversed = names.sort({ (s1: String, s2: String) -> Bool in return s1 > s2 }) ~~~ 當要運行的代碼很少時,你也可以將它們寫在一行。 ~~~ reversed = names.sort( { (s1: String, s2: String) -> Bool in return s1 > s2 } ) ~~~ ### 通過上下文判斷類型 在閉包中,我們不必寫參數的類型和返回值的類型,閉包可以通過上下文自動判斷參數類型和返回值類型。 ~~~ reversed = names.sort( { s1, s2 in return s1 > s2 } ) ~~~ ### 從單一表達式隱藏Return 在閉包中,如果運行的內容很少只有一行,則不必寫return,閉包會自動返回。 ~~~ reversed = names.sort( { s1, s2 in s1 > s2 } ) ~~~ ### 速記參數名稱 在閉包中,我們不必命名參數名稱。閉包中的參數可使用`$`去獲得,第一個參數為`$0`,第二個為`$1`。 ~~~ reversed = names.sort( { $0 > $1 } ) ~~~ ### 算子函數 當在閉包中,只有一個表達式,做操作。如在sort中,只有兩個參數做比較操作。閉包支持只輸入>或<做比較。 ~~~ reversed = names.sort(>) ~~~ ## 尾隨閉包 如果函數需要一個閉包作為參數,且這個參數是最后一個參數。我們又不想在()內寫太多代碼,我們可以運用尾隨閉包。尾隨閉包意味著閉包可以放在函數參數列表外,也就是括號外。 ~~~ var reversed = names.sort() { $0 > $1 } ~~~ 當尾隨閉包中的參數只有一個時,我們可以省略()。 ~~~ reversed = names.sort { $0 > $1 } ~~~ ## 捕獲值 閉包可以根據上下文環境捕獲到定義的常量和變量。閉包可以引用和修改這些捕獲到的常量和變量,就算在原來的范圍內定義為常量或者變量已經不再存在。在Swift中閉包的最簡單形式是嵌套函數。 ~~~ func makeIncrementer(forIncrement amount: Int) -> () -> Int { var runningTotal = 0 func incrementer() -> Int { runningTotal += amount return runningTotal } return incrementer } let incrementByTen = makeIncrementer(forIncrement: 10) print("\(incrementByTen())") // prints "10" print("\(incrementByTen())") // prints "20" print("\(incrementByTen())") // prints "30" ~~~ 上面的例子介紹了,有個函數makeIncrementer,在函數內有一個嵌套函數incremented。嵌套函數可以通過上下文使用它的外部值runningTotal和amount。 當你想聲明另一個閉包類型時,可以像聲明屬性一樣聲明。 ~~~ let incrementBySeven = makeIncrementer(forIncrement: 7) print("\(incrementBySeven())") // prints "7" print("\(incrementByTen())") // prints "40" ~~~ 可以看出兩個閉包的引用是完全獨立工作的。 ## 閉包是引用類型 運用屬性執行的閉包后,我們可以用另一個屬性去引用,對于兩個屬性來說,它們是完全相同的,指向同一個閉包。 ~~~ let alsoIncrementByTen = incrementByTen alsoIncrementByTen() // prints "50" ~~~ ## Noescape關鍵字 @noescape主要用于解決“保留環”問題如下所示,當你調用someFunctionWithEscapingClosure函數時,使用全局屬性,會使用了self,這樣你會發現每次調用閉包時,都會使用捕獲self,這樣容易造成內存泄露的問題,而且閉包中的操作其實是一成不變的,沒有必要每次都訪問。 Swift鑒于這種情況,希望在閉包內不使用self,因此產生了@noescape關鍵字。將@noescape寫入閉包名前。這樣在編寫閉包內代碼時,無須使用self屬性,也避免了保留環問題。 ~~~ var completionHandlers: [() -> Void] = [] func someFunctionWithNoescapeClosure(@noescape closure: () -> Void) { closure() // completionHandlers.append(closure) //會報錯,closure無法被保存 } func someFunctionWithEscapingClosure(completionHandler: () -> Void) { completionHandler() completionHandlers.append(completionHandler) } class SomeClass { var x = 10 func doSomething() { // 內存溢出,保留環問題 someFunctionWithEscapingClosure { self.x = 100 } someFunctionWithNoescapeClosure { x = 200 } } } let instance = SomeClass() instance.doSomething() print(instance.x) // prints "200" completionHandlers.first?() print(instance.x) // prints "100" ~~~ ## Autoclosures關鍵字 在閉包中,我們調用函數時,是將代碼封裝為一個閉包傳遞給函數。如下所示: ~~~ var customersInLine = ["Chris", "Alex", "Ewa", "Barry", "Daniella"] func serveCustomer(customerProvider: () -> String) { print("Now serving \(customerProvider())!") } serveCustomer( { customersInLine.removeAtIndex(0) } ) // prints "Now serving Alex!" ~~~ 此時我們會思考,能否讓代碼直接為參數傳遞過去,也就是不用{}包含代碼。@autoclosure關鍵字可以幫助你完成這種機制。 ~~~ // customersInLine is ["Ewa", "Barry", "Daniella"] func serveCustomer2(@autoclosure customerProvider: () -> String) { print("Now serving \(customerProvider())!") } // 閉包作為參數 serveCustomer2(customersInLine.removeAtIndex(0)) // prints "Now serving Ewa!" ~~~ 使用了@autoclosure默認也是使用@noescape,如果你只想使用autoclosure的特性,不想使用noescape的特性,你可以使用escape關鍵字,如下所示: ~~~ // customersInLine is ["Barry", "Daniella"] var customerProviders: [() -> String] = [] //autoclosure和escaping一起用 func collectCustomerProviders(@autoclosure(escaping) customerProvider: () -> String) { customerProviders.append(customerProvider) } // 添加閉包,并且閉包此時為參數 collectCustomerProviders(customersInLine.removeAtIndex(0)) collectCustomerProviders(customersInLine.removeAtIndex(0)) //循環使用閉包 for customerProvider in customerProviders { print("Now serving \(customerProvider())!") } // prints "Now serving Barry!" // prints "Now serving Daniella!" ~~~ ## 其他 ### 參考資料 [The Swift Programming Language (Swift 2.1)](https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/ErrorHandling.html) ### 文檔修改記錄 | 時間 | 描述 | |-----|-----| | 2015-10-28 | 根據 [The Swift Programming Language (Swift 2.1)](https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/ErrorHandling.html)中的Closures總結 | 版權所有:[http://blog.csdn.net/y550918116j](http://blog.csdn.net/y550918116j)
                  <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>

                              哎呀哎呀视频在线观看