![](/img/trans.png)
[英]How to fix escaping closure? Error is: Converting non-escaping value may allow it to escape
[英]Converting non-escaping value to 'Any' may allow it to escape error - within not escaping function
我的問題來自以下日本問題。 這不是我的問題,但我正在嘗試回答以下問題,但我找不到合適的答案。
https://teratail.com/questions/298998
上面的問題會像下面一樣簡單。
func executetwice(operation:() -> Void) {
print(operation)
operation()
}
這個編譯器要求在operation:
后加上@escaping
關鍵字operation:
label,如
func executetwice(operation: @escaping () -> Void) {
print(operation)
operation()
}
但實際上,似乎operation
塊並沒有從這個塊中逃脫。
其它的辦法,
func executetwice(operation:() -> Void) {
let f = operation as Any
operation()
}
編譯器還需要添加@escaping
關鍵字。 它只是向上轉換Any
。 在其他情況下,只是強制轉換為相同的類型,似乎是錯誤的。
func executetwice(operation:() -> Void) {
let f = operation as () -> Void //Converting non-escaping value to '() -> Void' may allow it to escape
operation()
}
我不確定為什么我需要添加沒有轉義條件的@escaping
關鍵字。
只需添加@escaping
關鍵字就可以了,但我想知道為什么編譯器在這種情況下需要關鍵字。
print
接受(可變數量的) Any
作為參數,所以這就是為什么當您將閉包傳遞給print
時,它說您將閉包轉換為Any
。
許多檢查應用於閉包類型的參數,以確保非轉義閉包不會轉義(關於閉包“轉義”的含義,請閱讀此內容):
var c: (() -> Void)?
func f(operation:() -> Void) {
c = operation // compiler can detect that operation escapes here, and produces an error
}
但是,這些檢查僅適用於閉包類型。 如果將閉包強制轉換為Any
,則該閉包會丟失其閉包類型,並且編譯器無法檢查它是否轉義。 假設編譯器允許您將非轉義閉包轉換為Any
,並且您將其傳遞給下面的g
:
var c: Any?
func g(operation: Any) {
// the compiler doesn't know that "operation" is a closure!
// You have successfully made a non-escaping closure escape!
c = operation
}
因此,編譯器被設計為保守的並將“強制轉換為Any
”視為“進行閉包逃逸”。
但是我們確信print
不會逃脫閉包,所以我們可以使用withoutActuallyEscaping
:
func executetwice(operation:() -> Void) {
withoutActuallyEscaping(operation) {
print($0)
}
operation()
}
將閉包轉換為它自己的類型也會使閉包逃逸。 這是因為operation as () -> Void
是一個“相當復雜”的表達式,產生類型() -> Void
。 “相當復雜”我的意思是它足夠復雜,以至於在將其傳遞給非轉義參數時,編譯器不會費心檢查您正在投射的內容是否真的是非轉義的,因此它假定所有類型轉換都在轉義.
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.