ios - Firebase Swift 3 数据库在 setValue withCompletionBlock 上崩溃

标签 ios swift firebase swift3 firebase-realtime-database

我在带有 Swift 3 的 iOS 上使用 Firebase。

当我使用

FIRDatabase.database().reference().child("child").setValue("value") { 
  (error: Error?, databaseReference: FIRDatabaseReference) in
    print("Error while setting value \(error)")
}   

应用程序在运行时崩溃并显示以下日志:

*** Terminating app due to uncaught exception 'InvalidFirebaseData', reason: '(nodeFrom:priority:) Cannot store object of type _SwiftValue at . Can only store objects of type NSNumber, NSString, NSDictionary, and NSArray.'

我尝试使用相同的函数,但没有尾随闭包,出于某种原因,它起作用了!

FIRDatabase.database().reference().child("child").setValue("value", 
  withCompletionBlock: { 
    (error: Error?, databaseReference: FIRDatabaseReference) in
      print("Error while setting value \(error)")
})

尾随闭包和 Swift 3 有什么特别之处吗?

最佳答案

tl;dr:Firebase 提供了一个 setValue(_ value: Any?, andPriority priority: Any?),当使用带有 setValue(_值:Any?, withCompletionBlock: (Error?, FIRDatabaseReference) -> Void)

解决方案:当使用具有多种变体的 API 时,避免使用尾随闭包。在这种情况下,更喜欢 setValue(myValue, withCompletionBlock: { (error, dbref) in/* ... */});不要使用setValue(myValue) { (error, dbref) in/* ... */

解释

这似乎是一个 Swift 错误。与其他语言(如 Java)一样,Swift 通常会选择最具体的重载。例如,

class Alpha {}
class Beta : Alpha {}

class Charlie {
    func charlie(a: Alpha) {
        print("\(#function)Alpha")
    }
    func charlie(a: Beta) {
        print("\(#function)Beta")
    }
}

Charlie().charlie(a: Alpha()) // outputs: charlie(a:)Alpha
Charlie().charlie(a: Beta() as Alpha) // outputs: charlie(a:)Alpha
Charlie().charlie(a: Beta()) // outputs: charlie(a:)Beta

然而,当重载函数匹配尾随闭包时,Swift(至少,有时)会选择更通用的类型。例如,

class Foo {
    func foo(completion: () -> Void) {
        print(#function)
    }
    func foo(any: Any?) {
        print(#function)
    }
}

func bar() {}
Foo().foo(completion: bar) // outputs: foo(completion:)
Foo().foo(any: bar) // outputs: foo(any:)
Foo().foo() { () in } // outputs: foo(any:)
// ^---- Here lies the problem
// Foo().foo(bar) will not compile; can't choose between overrides.

Any? 是比 () -> Void 更通用的类型——也就是说,“任何东西,甚至是 null”比“接收 0 个参数的函数”更广泛并返回 Void 类型的内容”。但是,尾随闭包匹配 Any?;这与您对匹配最特定类型的语言的期望相反。

关于ios - Firebase Swift 3 数据库在 setValue withCompletionBlock 上崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41406567/

相关文章:

ios - 是否有从 firebase 实时数据库中获取 n 个元素的功能?

Firebase云函数: Error: Unexpected error while acquiring application default credentials: read ECONNRESET

ios - 在 HMEventTrigger 启用触发器中显示错误

ios - prepareForSegue 如何工作? (将数据传递给下一个 View Controller )

ios - 将数据传递到tableViewController时出错

ios - 如何将 .jpeg/.tiff 图像保存到 iOS 中的设备库中

ios - UIScrollview 为 subview 添加一些额外的空间

Swift 4 NSPredicate 日期格式不起作用

ios - 有些 UIColors 是黑色的,而不是它们应该的样子,为什么?

android - 如何从android中的firebase数据库中检索特定节点