我有以下功能,我有完成处理程序,但我收到此错误:
Closure use of non-escaping parameter may allow it to escape
这是我的代码:
func makeRequestcompletion(completion:(_ response:Data, _ error:NSError)->Void) {
let urlString = URL(string: "http://someUrl.com")
if let url = urlString {
let task = URLSession.shared.dataTask(with: url, completionHandler: { (data, urlRequestResponse, error) in
completion(data, error) // <-- here is I'm getting the error
})
task.resume()
}
}
我真的很感谢你的帮助
答案 0 :(得分:8)
看起来你需要明确定义允许关闭转义。
当闭包作为参数传递给函数时,闭包被称为转义函数,但在函数返回后调用。当声明一个以闭包作为其参数之一的函数时,可以在参数的类型之前编写@escaping,以指示允许闭包转义。
TLDR;在完成变量之后添加class common {
friend class mode1;
friend class mode2;
protected:
volatile uint8_t& reg1;
volatile uint8_t& reg2;
uint8_t data;
public:
virtual void operation2() final { // do something
};
};
class mode1 : public virtual common
{
public:
virtual void operation1() final { // do something
};
virtual void operation3() final { // do something }
};
};
class mode2 : public virtual common
{
public:
virtual void operation4() final { // do something
}
virtual void operation5() final { // do something
}
};
class mode1and2 : public mode1, public mode2
{
public:
void operation6() { // do something }
};
void operation7() { // do something }
};
};
关键字:
@escaping
答案 1 :(得分:3)
&#34;逃避&#34;闭包是一个闭包,它可以比它创建的范围更长。转出闭包需要特别注意引用计数和内存管理,并且可能更难以优化。
在Swift 3之前,闭包的默认设置是假设它们正在转义。这意味着开发人员必须专门识别已知 not 的闭包以允许编译器进行优化。社区发现事实上,编译器可以很容易地找出闭包是否转出,并决定一种积极的转义方法可以导致更快的代码。结果是现在假定闭包是非转义的,并且您需要标记使用@escaping
属性转义的闭包。
在你的情况下,URLSession.shared.dataTask
接受的闭包本身就是一个转义闭包,所以如果在其中使用闭包,它也需要标记为@escaping
。
答案 2 :(得分:1)
@escaping
对所有调用方法都有感染力,编译器会确定必须包含它的时间。
考虑这个例子(编译):
dispatchSometime( { print("Oh yeah") })
func dispatchSometime(_ block: ()->()) {
dispatchNow(block)
}
func dispatchNow(_ block: ()->()) {
block()
}
但是,此修改示例会产生类型为non-escaping parameter may allow it to escape
的两个错误:
dispatchSometime( { print("Oh yeah") })
func dispatchSometime(_ block: ()->()) {
dispatchLater(block)
}
func dispatchLater(_ block: ()->()) {
DispatchQueue.main.async(execute: block)
}
在main上发送意味着dispatchLater
方法需要@escaping
,一旦您添加了该方法,dispatchSometime
方法也需要{{ 1}}用于编译的示例。
@escaping
然而,带走只是:
dispatchSometime( { print("Oh yeah") })
func dispatchSometime(_ block: @escaping ()->()) {
dispatchLater(block)
}
func dispatchLater(_ block: @escaping ()->()) {
DispatchQueue.main.async(execute: block)
}
,直到编译器停止抱怨。 @escaping
捕获的变量,因为它们可能与块本身一起保留&#34; <强>启示强>
真正有趣的情况是你需要调整几个方法来包含weak
关键字,这会让编译器停止抱怨。但是,如果这些方法实际上符合协议,那么该协议的方法必须也获取@escaping
关键字,这也会感染所有其他协议符合性。有趣!