我正在使用 Firebase 观察事件,然后在完成处理程序中设置图像
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")!
}
})
但是我收到此错误
Closure cannot implicitly capture a mutating self parameter
我不确定这个错误是什么,并且搜索解决方案没有帮助
最佳答案
简短版本
拥有您对 FirebaseRef.observeSingleEvent(of:with:)
的调用的类型最有可能是值类型(a struct
?),在这种情况下,变异上下文可能不会显式捕获 self
在 @escaping
关闭。
简单的解决方案是将您的拥有类型更新为引用一次 ( class
)。
较长版本
observeSingleEvent(of:with:)
method of Firebase声明如下
func observeSingleEvent(of eventType: FIRDataEventType, with block: @escaping (FIRDataSnapshot) -> Void)
block
关闭标有 @escaping
参数属性,这意味着它可能会转义其函数体,甚至 self
的生命周期(根据您的情况)。利用这些知识,我们构建了一个可以分析的更简单的示例:
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 */
}
}
现在,错误消息变得更加明显,我们转向在 Swift 3 中实现以下演化提案:
声明[强调我的]:
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).
现在,这是一个关键点。对于 value 类型(例如 struct
),我相信拥有对 observeSingleEvent(...)
调用的类型也是如此。在您的示例中,这样的显式捕获是不可能的,afaik(因为我们正在使用值类型,而不是引用类型)。
此问题最简单的解决方案是创建拥有 observeSingleEvent(...)
的类型引用类型,例如一个class
,而不是 struct
:
class Foo {
init() {}
private func bar(with block: @escaping () -> ()) { block() }
func bax() {
bar { print(self) }
}
}
请注意,这将捕获 self
通过强有力的引用;根据您的上下文(我自己没有使用过 Firebase,所以我不知道),您可能需要显式捕获 self
弱,例如
FirebaseRef.observeSingleEvent(of: .value, with: { [weak self] (snapshot) in ...
关于ios - 闭包无法隐式捕获变异的 self 参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59961703/