我正在使用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")!
        }
})

然而,我得到了这个错误

闭包不能隐式捕获变异的self参数

我不确定这个错误是怎么回事,寻找解决方案也无济于事

推荐答案

The short version

您拨打FirebaseRef.observeSingleEvent(of:with:)的电话类型很可能是值类型(a struct?),在这种情况下,变异上下文可能不会在@escaping闭包中显式捕获self.

简单的解决方案是将您拥有的类型更新为引用一次(class).


The longer version

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中实施的以下演进方案:

陈述[强调我的]:

捕获inout参数including 101 in a mutating method变成可回避闭包文字unless the capture is made explicit中的错误(因此是不可变的).

现在,这是一个关键点.对于value类型(例如struct),我相信在您的示例中拥有observeSingleEvent(...)调用的类型也是如此,这样的显式捕获是不可能的,因为我们使用的是值类型,而不是引用类型.

此问题的最简单解决方案是将拥有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相关问答推荐

StackView UIKit间距似乎非常小的编程式编程

UIImage大小调整工作,但转换为上传数据时恢复到原始大小

在选项卡内列出导航内视图断开导航标题的动画

在flutter中使用flatter_screenutil这样的软件包的目的是什么?

如何在HStack中将sfsymbol与Text视图对齐?

如何在 Swift 中存储具有关联值的协议?

分配给指针会通过 class_addMethod 导致 EXC_BAD_ACCESS

如何使用自定义数据源在本地react 本机 ios 应用程序中加载 Tradingview 小部件?

无法使用 NavigationView 和 NavigationLink 在 SwiftUI 中弹出当前屏幕

发生错误.请稍后重试.在 App Store 连接中

在 SwiftUI 中以编程方式插入内嵌图像

查找东南亚语言(泰语、高棉语、老挝语、缅甸语)中的单词边界

使用 Apollo 发布 iOS 应用程序时缺少推送通知权利

如何判断 `NSManagedObject` 是否已被删除?

iPhone iOS 无法正确显示 box-shadow

NSURLConnection 的 Xcode 4 警告未使用表达式结果

不变违规:应用程序 AwesomeProject 尚未注册使用静态 jsbundle 为 iOS 设备构建时

iOS 应用程序中的手动语言 Select (iPhone 和 iPad)

iOS:如何从 URL 调试新启动应用程序

如何使用 AFNetworking 设置超时