闭包不能隐式捕获变异的 self 参数 [英] Closure cannot implicitly capture a mutating self parameter
问题描述
我使用 Firebase 观察事件,然后在完成处理程序中设置图像
FirebaseRef.observeSingleEvent(of: .value, with: { (snapshot) in如果让 _ = snapshot.value 作为?NSNull {self.img = UIImage(named:"Some-image")!} 别的 {self.img = UIImage(named: "some-other-image")!}})
但是我收到此错误
<块引用>Closure 不能隐式捕获变异的 self 参数
我不确定这个错误是关于什么的,搜索解决方案也没有帮助
简短版
拥有您对 FirebaseRef.observeSingleEvent(of:with:)
的调用的类型很可能是值类型(struct
?),在这种情况下是一个可变上下文可能不会在 @escaping
闭包中显式捕获 self
.
简单的解决方案是将您拥有的类型更新为一次引用(class
).
更长的版本
observeSingleEvent(of:with:)
Firebase 的方法声明如下
func observeSingleEvent(of eventType: FIRDataEventType,带块:@escaping (FIRDataSnapshot) ->空白)
block
闭包标有 @escaping
参数属性,这意味着它可能会转义其函数体,甚至是 self<的生命周期/code>(在您的上下文中).使用这些知识,我们构建了一个更小的例子,我们可以分析:
struct Foo {private func bar(with block: @escaping () -> ()) { block() }变异 func bax() {bar { print(self) }//这个闭包可能比self"更长寿/* 错误:闭包不能隐式捕获一个变异自参数 */}}
现在,错误信息变得更有说服力,我们转向以下在 Swift 3 中实现的进化提议:
声明[强调我的]:
<块引用>捕获一个 inout
参数,在变异中包含 self
方法,成为可转义闭包文字中的错误,除非捕获是明确的(因此是不可变的).
现在,这是一个关键点.对于 value 类型(例如 struct
),我相信拥有对 observeSingleEvent(...)
在您的示例中,这样的显式捕获是不可能的,afaik(因为我们正在使用值类型,而不是引用类型).
解决这个问题的最简单的方法是使拥有 observeSingleEvent(...)
的类型成为引用类型,例如一个 class
,而不是一个 struct
:
class Foo {在里面() {}private func bar(with block: @escaping () -> ()) { block() }功能 bax() {酒吧{打印(自我)}}}
请注意,这将通过强引用捕获self
;根据您的上下文(我自己没有使用过 Firebase,所以我不知道),您可能希望弱地明确捕获 self
,例如
FirebaseRef.observeSingleEvent(of: .value, with: { [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 ...
这篇关于闭包不能隐式捕获变异的 self 参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!