example configurar con agregar ios swift firebase swift3 firebase-database

ios - configurar - La base de datos de Firebase Swift 3 se bloquea en setValue withCompletionBlock



firebase ios swift example (2)

Si bien hay una respuesta aceptada, que proporciona cierta claridad, explicar que es un error Swift no es realmente precisa. Dicho esto, la explicación es precisa, pero no para este tema.

Permitir que el cierre se agregue a setValue en primer lugar es el verdadero error.

Una respuesta más precisa es que no existe un bloqueo / cierre de finalización para la función setValue , por lo que falla.

La función específica -setValue: NO tiene cierre, por lo que se bloquea. es decir, es una implementación incorrecta en su código. Por los documentos:

func setValue(_ value: Any?)

tenga en cuenta que la función setValue NO tiene un cierre y si agrega una, la función no tendrá idea de qué hacer con esa información.

Para usar un bloqueo / cierre de finalización, debe llamar a la función correcta que es

-setValue:withCompletionBlock:

En pocas palabras, no puede agregar aleatoriamente un parámetro o llamar a una función que no está diseñada para aceptarlo.

Obviamente, esto no es válido, pero conceptualmente es el mismo error.

let a = "myString" a.append("x") { (error: Error?) }

En este caso, el compilador sabe que la función string.append no tiene una opción de cierre y la captura antes de compilar.

Así que vaya un poco más, este código cumple y se ejecuta, pero también genera un error

ref.child("child").setValue("value") { }

De nuevo, setValue no tiene cierre, por lo que este código no se implementa correctamente.

Para aclarar, dada una clase

class MyClass { var s = "" var compHandler = {} func setValue(aString: String) { self.s = aString } func setValue(aString: String, someCompletionHandler: completionHandler) { self.s = aString self.compHandler = someCompletionHandler } }

Tenga en cuenta que setValue: aString es una función totalmente diferente de setValue: aString: someCompletionHandler

El único parámetro que puede basarse en setValue: aString es una cadena como el primer y único parámetro.

SetValue: aString: someCompletionHandler recibirá dos parámetros, un String en la primera posición y un completionHandler en la segunda posición.

El bloque de finalización real es el segundo parámetro pasado.

param1, param2 ------, --------------- cadena, completionBlock

Esta es la razón por

setValue(value) {}

está incorrectamente formateado mientras

setValue(value, withBlock: {})

está apropiadamente formateado

Estoy usando Firebase en iOS con Swift 3.

Cuando uso

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

La aplicación se bloquea en tiempo de ejecución con el siguiente registro:

*** Aplicación de finalización debido a una excepción no detectada ''InvalidFirebaseData'', razón: ''(nodeFrom: priority :) No se puede almacenar el objeto de tipo _SwiftValue en. Solo puede almacenar objetos de tipo NSNumber, NSString, NSDictionary y NSArray. ''

Traté de usar la misma función pero sin el cierre posterior y por alguna razón, ¡funciona!

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

¿Hay algo especial acerca de los cierres finales y Swift 3?


tl; dr: Firebase proporciona un setValue(_ value: Any?, andPriority priority: Any?) que coincide incorrectamente cuando se usa un cierre posterior con setValue(_ value: Any?, withCompletionBlock: (Error?, FIRDatabaseReference) -> Void)

Solución : cuando se usa una API que tiene muchas variedades, evite el uso de cierres finales. En este caso, prefiera setValue(myValue, withCompletionBlock: { (error, dbref) in /* ... */ }) ; no use setValue(myValue) { (error, dbref) in /* ... */ } .

Explicación

Esto parece ser un error Swift. Al igual que en otros lenguajes, como Java, Swift generalmente elige la sobrecarga más específica. P.ej,

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

Sin embargo, cuando las funciones sobrecargadas coinciden con un cierre posterior, Swift (al menos, algunas veces) selecciona el tipo más general. P.ej,

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? es un tipo más general que () -> Void - es decir, "cualquier cosa, incluso nulo" es más amplio que "una función que recibe 0 parámetros y devuelve algo del tipo Void ". Sin embargo, ¿el cierre final coincide con Any? ; esto es lo contrario de lo que esperaría de un idioma que coincida con el tipo más específico.