![](/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.