[英]Swift optional escaping closure
編譯器錯誤Closure use of non-escaping parameter 'completion' may allow it to escape
,這是有道理的,因為它將在函數返回后調用。
func sync(completion:(()->())) {
self.remoteConfig.fetch(withExpirationDuration: TimeInterval(expirationDuration)) { (status, error) -> Void in
completion()
}
}
但是,如果我將閉包設為可選,則不會出現編譯器錯誤,那是為什么呢? 函數返回后仍可以調用閉包。
func sync(completion:(()->())?) {
self.remoteConfig.fetch(withExpirationDuration: TimeInterval(expirationDuration)) { (status, error) -> Void in
completion?()
}
}
將閉包包裝在Optional中會自動將其轉義。 從技術上講,它已經被嵌入枚舉(“可選”)“轉義”了。
為了理解這種情況,實現以下代碼將很有用:
typealias completion = () -> ()
enum CompletionHandler {
case success
case failure
static var handler: completion {
get { return { } }
set { }
}
}
func doSomething(handlerParameter: completion) {
let chObject = CompletionHandler.handler = handlerParameter
}
乍一看,此代碼似乎合法,但事實並非如此! 您將收到編譯時錯誤抱怨:
錯誤 :將非轉義參數'handlerParameter'分配給@轉義閉包
讓chObject = CompletionHandler.handler = handlerParameter
注意:
注意 :參數'handlerParameter'是隱式非轉義函數doSomething(handlerParameter:完成){
這是為什么? 假設代碼片段與@escaping
沒有@escaping
...
實際上,由於Swift 3已發布,因此默認情況下,如果在enum , struct或class中聲明了閉包,則閉包將被“轉義”。
作為參考,報告了與該問題有關的錯誤:
盡管它們可能與本案並非100%相關,但受讓人的評論清楚地描述了該案:
第一條評論 :
這里的實際問題是, 可選的閉包現在隱式@轉義。
第二條評論 :
不幸的是,Swift 3就是這種情況。這是Swift 3中轉義的語義:
1)默認情況下,函數參數位置的閉包不轉義
2) 所有其他關閉都在逃逸
因此,所有通用類型參數閉包(例如Array和Optional )都在轉義。
顯然, Optional
是枚舉。
同樣-如上所述,相同的行為也適用於類和結構:
類案例:
typealias completion = () -> ()
class CompletionHandler {
var handler: () -> ()
init(handler: () -> ()) {
self.handler = handler
}
}
func doSomething(handlerParameter: completion) {
let chObject = CompletionHandler(handler: handlerParameter)
}
結構案例:
typealias completion = () -> ()
struct CompletionHandler {
var handler: completion
}
func doSomething(handlerParameter: completion) {
let chObject = CompletionHandler(handler: handlerParameter)
}
上面的兩個代碼段將導致相同的輸出(編譯時錯誤)。
為了解決這個問題,您需要讓函數簽名為 :
func doSomething( handlerParameter: @escaping completion)
因為您期望您必須讓completion:(()->())?
為了逃脫,這將自動完成-如上所述-。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.