Recibí una notificación en didreceiveRemoteNotification pero no puedo enviar información de usuario al diccionario de tipo [String: Any]
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) { let dict = userInfo as! [String: Any] if let response = dict["message"] as? [String: Any], let baseResponse = Mapper<NotificationModel>().map(JSON: response) { //do some stuff } }cuando trato de lanzar dict["mensaje"] como! [String: Any] ocurre un error y dice:
No se pudo convertir el valor de tipo '__NSCFString' (0x1cfa84f90) a 'NSDictionary' (0x1cfa85bc0).
Aquí está dict["message"] cuando lo imprimo en la consola:
▿ Optional<Any> - some : {"sender": {"avatar_url":"http:\/\/api.moneyar.com\/APIs\/images\/15783070400.jpg","user_id":"15783","name":"mahdi moqadasi"} ,"conversation_id":"15783" ,"message_id":103597, "time":1546778745, "type":1,"message":"foo" }Para la siguiente respuesta, el código no se prueba contra un compilador, puede haber algún problema de error tipográfico que podría solucionarse fácilmente, algunos de ellos se realizan intencionalmente para ejercer la lógica detrás de él, y no se agregan con if let / guard let , as? , etc. que son necesarios pero agregan ruido en la explicación.
No repetiré la respuesta de @vadian , que es correcta y explica por qué falla.
Así que tenemos claro que dict["message"] es un String .
Una información que parece faltar en el acrónimo JSON es lo que significa la notación "N".
Cuando imprimió dict["message"] , realmente no tenía un objeto clave/valor, tiene una Cadena que representa un objeto clave-valor, pero no en una representación de Swift. Imprimió JSON Stringified (porque es claramente más legible que JSON de datos hexadecimales). Si después de la respuesta imprime jsonDict , verá que la estructura de salida puede ser diferente.
Entonces, como siempre, tus herramientas básicas son:
Data <== data(encoding:)/init(data:encoding:) ==> String Data <== jsonObject(with:options:)/data(withJSONObject:options:) ==> Array or Dictionary //I bypass voluntarily the specific case of String at top level¡Hagamoslo entonces!
let jsonStringifiedString = dict["message"] as String let jsonStringifiedData = jsonStringifiedString.data(using: .utf8) as Data let jsonDict = try JSONSerialization.jsonObject(with: jsonStringifiedData, options: []) as [String: Any] let baseResponse = Mapper<NotificationModel>().map(JSON: jsonDict) Si yo fuera usted, buscaría en Mapper si no hay forma de hacer algo como:
let baseResponse = Mapper<NotificationModel>().map(JSONData: jsonStringifiedData)o
let baseResponse = Mapper<NotificationModel>().map(JSONString: jsonStringifiedString) Debido a que a veces hay JSONStringified incrustado en JSON, donde es posible que deba llamarlo en una String o en un Data directamente. O simplemente porque la solicitud básica URLSession devuelve un objeto de Data en su cierre y desea usarlo directamente.
El error
No se pudo convertir el valor de tipo '__NSCFString' (0x1cfa84f90) a 'NSDictionary' (0x1cfa85bc0).
es claro. El valor del message clave es una cadena.
if let response = dict["message"] as? String, ...