ios - 闭包无法隐式捕获变异的 self 参数

标签 ios swift firebase swift3 firebase-realtime-database

我正在使用 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, including self 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/

相关文章:

java - 如何在 firebase 中获取所有 child 的数据并将其显示到我的 Android 应用程序中?

arrays - 计算 Firebase (Swift) 的结果数

ios - Swift 如何在集合单元格中包装标签的长文本并在文本标签中设置边距

swift : Anchor SKSpriteNode

swift - Foursquare:iOS 同一地点的用户数量

ios - Firebase Analytics - 自定义事件,查看百分比而不是值 (iOS)

ios - 如何在 Swift 4 中从 WKWebView 获取 cookie 值?

ios - Bundle 无效 Xcode 发布错误

ios - UIBarButtonItem 点击区域

swift - 应用程序在前台使用 CoreML,GPU 在前台,当应用程序转到后台时,无法切换到 CPU