Firebase Swift 3数据库在setValue withCompletionBlock上崩溃 [英] Firebase Swift 3 Database crashes on setValue withCompletionBlock

查看:157
本文介绍了Firebase Swift 3数据库在setValue withCompletionBlock上崩溃的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在Swift 3上使用了Firebase。



当我使用

 <在
中打印(code> FIRDatabase.database()。reference()。child(child).setValue(value){
(error:Error ?, databaseReference:FIRDatabaseReference) 设置值时出错\(错误))
}

应用程序崩溃运行时使用以下日志:
$ b


***由于未捕获异常InvalidFirebaseData,终止应用程序,原因:'(nodeFrom:priority :)无法存储_SwiftValue
类型的对象。只能存储类型为NSNumber,NSString,NSDictionary,
和NSArray的对象。'


我尝试使用相同的函数但是没有尾随的关闭,出于某种原因,它是有效的!

  FIRDatabase.database()。reference()。child( (错误)设置值时出错(错误))
print(Errorwhile setting value \(error))
))

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

解决方案

tl; dr:Firebase提供了一个 setValue(_ value:Any ?,和优先级优先级:任何? ) setValue(_ value:Any?,withCompletionBlock:(Error?,FIRDatabaseReference) - > Void) c>。



解决方案:使用多种类型的API时,追尾关闭。在这种情况下,首选 setValue(myValue,withCompletionBlock:{(error,dbref)in / * ... * /});在/ * ... * /} 中使用 setValue(myValue){(error,dbref)来执行 。 b

解释

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

  class Alpha {} 
class Beta:Alpha {}

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

charlie(a:Alpha())//输出:charlie(a: )char $(a:Beta())//输出:charlie():char $(char)然而,当重载函数匹配结尾的闭包时,Swift(至少,它是一个函数)有时)选择更一般的类型。例如,

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

func bar(){}
Foo().foo(completion:bar)//输出:foo(完成:)
Foo().foo(any:bar)// outputs:foo(any :)
Foo()。foo(){()in} //输出:foo(any :)
// ^ ----这就是问题
// Foo ).foo(bar)不会编译;无法在覆盖之间进行选择。

任何? () - > Void - 即nothing,even null比接收0个参数并返回类型 Void >的函数更广泛。但是,结尾匹配符合 Any?;这与你所期望的与最具体类型匹配的语言是相反的。


I am using Firebase on iOS with Swift 3.

When I use

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

The app crashes on runtime with the following log:

*** 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.'

I tried to use the same function but without the trailing closure and for some reason, it works!

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

Is there something special about trailing closures and Swift 3?

解决方案

tl;dr: Firebase provides a setValue(_ value: Any?, andPriority priority: Any?) which is incorrectly matched when using a trailing closure with setValue(_ value: Any?, withCompletionBlock: (Error?, FIRDatabaseReference) -> Void).

Solution: When using an API that has many varieties, avoid using trailing closures. In this case, prefer setValue(myValue, withCompletionBlock: { (error, dbref) in /* ... */ }); do not use setValue(myValue) { (error, dbref) in /* ... */ }.

Explanation

This appears to be a Swift bug. As in other languages, such as Java, Swift generally chooses the most specific overload. E.g.,

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

However, when overloaded functions match a trailing closure, Swift (at least, sometimes) selects the more general type. E.g.,

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? is a more general type than () -> Void -- i.e., "anything, even null" is more broad than "a function receiving 0 parameters and returning something of type Void". However, the trailing closure matches Any?; this is the opposite of what you would expect from a language that matches the most specific type.

这篇关于Firebase Swift 3数据库在setValue withCompletionBlock上崩溃的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆