闭包不能隐式捕获一个变异的自参数 [英] Closure cannot implicitly capture a mutating self parameter
问题描述
我使用Firebase观察事件,然后在完成处理程序中设置图像
FirebaseRef.observeSingleEvent(of:.value ,如下:{(snapshot)in
if _ = snapshot.value as?NSNull {
self.img = UIImage(named:Some-image)!
} else {
self.img = UIImage(命名为some-other-image)!
}
})
然而,我得到这个错误
Closure不能隐式捕获一个变异的自我参数
我不确定这个错误是什么,寻找解决方案并没有帮助
struct
?),在这种情况下,变异的上下文可能不会明确地捕获自
在 @escaping
闭包中。简单的解决方案是将拥有的类型更新为引用一次( class
)。
版本
的方法,您可以使用以下方法来查看FireShell脚本:声明如下:
$ b
func observeSingleEvent(eventType:FIRDataEventType,
with block :@escaping(FIRDataSnapshot) - >无效)
block
闭包被标记为 @escaping
参数属性,这意味着它可以转义它的函数体,甚至 self的生命期
(在你的上下文中)。使用这些知识,我们构建了一个更简单的例子,我们可以分析:
$ $ p $ struct $ F $ {b $ b private func bar( (){block()}>()){block()}
mutating func bax(){
bar {print(self)} // this closure may outlive' self'
/ * error:closure不能隐式地捕获
变异的自参数* /
}
}
现在,错误信息变得更加明显,我们转向Swift 3中实现的以下演变提议:
说明[强调我的]:
捕获
inout
参数,包括self
在一个mutatin中g
方法,在可变的闭包文字中变成了一个错误,除非
捕获是明确的(从而是不可变的)。 b
现在,这是一个关键点。对于值类型(例如 struct
),我认为对于拥有在你的例子中,observeSingleEvent(...)
,这样的显式捕获是不可能的,afaik(因为我们正在使用一个值类型,而不是一个引用)。
这个问题最简单的解决方法是使类型拥有 observeSingleEvent(...)
引用类型,例如一个 class
,而不是一个 struct
:
<$ p $ ($)$ {
init(){}
private func bar(with block:@escaping() - >()){block()}
func bax(){
bar {print(self)}
}
}
请注意,这将通过强引用捕获 self
;取决于你的上下文(我自己并没有使用Firebase,所以我不知道),你可能希望明确地捕获 self
,例如
FirebaseRef.observeSingleEvent(of:.value,与:{[weak self](snapshot)in ...
I am using Firebase to observe event and then setting an image inside completion handler
FirebaseRef.observeSingleEvent(of: .value, with: { (snapshot) in
if let _ = snapshot.value as? NSNull {
self.img = UIImage(named:"Some-image")!
} else {
self.img = UIImage(named: "some-other-image")!
}
})
However I am getting this error
Closure cannot implicitly capture a mutating self parameter
I am not sure what this error is about and searching for solutions hasn't helped
The short version
The type owning your call to FirebaseRef.observeSingleEvent(of:with:)
is most likely a value type (a struct
?), in which case a mutating context may not explicitly capture self
in an @escaping
closure.
The simple solution is to update your owning type to a reference once (class
).
The longer version
The observeSingleEvent(of:with:)
method of Firebase is declared as follows
func observeSingleEvent(of eventType: FIRDataEventType, with block: @escaping (FIRDataSnapshot) -> Void)
The block
closure is marked with the @escaping
parameter attribute, which means it may escape the body of its function, and even the lifetime of self
(in your context). Using this knowledge, we construct a more minimal example which we may analyze:
struct Foo {
private func bar(with block: @escaping () -> ()) { block() }
mutating func bax() {
bar { print(self) } // this closure may outlive 'self'
/* error: closure cannot implicitly capture a
mutating self parameter */
}
}
Now, the error message becomes more telling, and we turn to the following evolution proposal was implemented in Swift 3:
Stating [emphasis mine]:
Capturing an
inout
parameter, includingself
in a mutating method, becomes an error in an escapable closure literal, unless the capture is made explicit (and thereby immutable).
Now, this is a key point. For a value type (e.g. struct
), which I believe is also the case for the type that owns the call to observeSingleEvent(...)
in your example, such an explicit capture is not possible, afaik (since we are working with a value type, and not a reference one).
The simplest solution to this issue would be making the type owning the observeSingleEvent(...)
a reference type, e.g. a class
, rather than a struct
:
class Foo {
init() {}
private func bar(with block: @escaping () -> ()) { block() }
func bax() {
bar { print(self) }
}
}
Just beware that this will capture self
by a strong reference; depending on your context (I haven't used Firebase myself, so I wouldn't know), you might want to explicitly capture self
weakly, e.g.
FirebaseRef.observeSingleEvent(of: .value, with: { [weak self] (snapshot) in ...
这篇关于闭包不能隐式捕获一个变异的自参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!