将 userInfo [AnyHashable: Any] 转换为 [String: Any]

and*_*fan 7 push-notification apple-push-notifications swift

我收到通知didreceiveRemoteNotification但无法将 userInfo 转换为 [String: Any] 类型的字典

\n\n
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {\n    let dict = userInfo as! [String: Any]\n    if let response = dict["message"] as? [String: Any], let baseResponse = Mapper<NotificationModel>().map(JSON: response) {\n      //do some stuff\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

当我尝试将 dict["message"] 转换为![字符串:任何] 发生错误,并显示:

\n\n

无法将类型“__NSCFString”(0x1cfa84f90)的值转换为“NSDictionary”(0x1cfa85bc0)。

\n\n

当我在控制台中打印它时,这是 dict["message"] :

\n\n
\xe2\x96\xbf Optional<Any>\n  - some : {"sender":\n\n{"avatar_url":"http:\\/\\/api.moneyar.com\\/APIs\\/images\\/15783070400.jpg","user_id":"15783","name":"mahdi moqadasi"}\n\n,"conversation_id":"15783"\n\n,"message_id":103597,\n\n"time":1546778745,\n\n"type":1,"message":"foo"\n\n}\n
Run Code Online (Sandbox Code Playgroud)\n

Lar*_*rme 4

对于以下答案,代码没有针对编译器进行测试,可能存在一些可以轻松修复的拼写错误问题,其中一些是故意执行的以推断其背后的逻辑,而不是添加if let/ guard letas?等。需要,但会在解释中添加噪音。

我不会重复@vadian 的答案,这是正确的并解释了它失败的原因。

所以我们很清楚这dict["message"]是一个String.

您在 JSON 首字母缩略词中似乎缺少的一条信息是“N”的含义:表示法。

当你打印 时dict["message"],你并没有真正的键/值对象,你有一个代表键值对象的 String ,但不是 Swift 表示形式。您打印了 JSON Stringified(因为它显然比十六进制数据 JSON 更具可读性)。如果在打印答案后jsonDict,您会发现输出结构可能有所不同。

因此,一如既往,您的基本工具是:

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
Run Code Online (Sandbox Code Playgroud)

那我们就开始吧!

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)
Run Code Online (Sandbox Code Playgroud)

如果我是你,我会研究Mapper是否没有办法做这样的事情:

let baseResponse = Mapper<NotificationModel>().map(JSONData: jsonStringifiedData)
Run Code Online (Sandbox Code Playgroud)

或者

let baseResponse = Mapper<NotificationModel>().map(JSONString: jsonStringifiedString)
Run Code Online (Sandbox Code Playgroud)

因为有时 JSON 中嵌入了 JSONStringified,您可能需要直接在 aString或 a 上调​​用它Data。或者只是因为基本URLSession请求在其闭包中返回一个Data对象,而您想直接使用它。