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

Swift 将userInfo[AnyHashable:Any]转换为[String:Any],swift,push-notification,apple-push-notifications,Swift,Push Notification,Apple Push Notifications,我在didReceiveMemoteNotification中收到通知,但我无法将userInfo强制转换为类型为[String:Any]的字典 func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetch

我在
didReceiveMemoteNotification
中收到通知,但我无法将userInfo强制转换为类型为[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
    }
}
func应用程序(application:UIApplication,DidReceiveMemoteNotification用户信息:[AnyHashable:Any],fetchCompletionHandler completionHandler:@escaping(UIBackgroundFetchResult)->Void){
让dict=userInfo as![String:Any]
如果让response=dict[“message”]作为?[String:Any],则让baseResponse=Mapper().map(JSON:response){
//做点什么
}
}
当我试图将dict[“message”]转换为![String:Any]发生错误并显示:

无法将“\uu NSCFString”(0x1cfa84f90)类型的值强制转换为“NSDictionary”(0x1cfa85bc0)。

当我在控制台中打印时,这里是dict[“message”]:

▿ 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"

}
▿ 可选的
-一些:{“发件人”:
{“阿凡达url”:“http:\/\/api.moneyar.com\/api\/images\/15783070400.jpg”,“用户id:“15783”,“姓名:“mahdi moqadasi”}
,“对话id”:“15783”
,“消息id”:103597,
“时间”:1546778745,
“类型”:1,“消息”:“foo”
}
错误

无法将类型为“\uu NSCFString”(0x1cfa84f90)的值强制转换为“NSDictionary”(0x1cfa85bc0)

这是清楚的。键
message
的值是一个字符串

  • 类型的是真正的类型
  • 是预期的错误类型


对于下面的答案,代码没有针对编译器进行测试,可能存在一些容易修复的输入错误问题,其中一些问题是故意执行其背后的逻辑,而不是添加
(如果let
/
保护let
as?
)等,这是需要的,但会在解释中添加噪音

我不重复了,这是正确的解释为什么它失败了

所以我们很清楚,
dict[“message”]
是一个
字符串

JSON首字母缩略词中缺少的一条信息代表“N”:符号

当您打印
dict[“message”]
时,您没有真正的键/值对象,您有一个表示键/值对象的字符串,但不是Swift表示形式。您将JSON字符串化(因为它显然比十六进制数据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

let baseResponse=Mapper().map(JSONString:jsonstringfiedstring)
因为JSON中有时会嵌入JSONString,您可能需要直接在
字符串
数据
上调用它。
或者仅仅因为基本的
URLSession
请求在其闭包中返回了一个
数据
对象,而您想要直接使用它。

这不是答案。我打印dict[/message],一切都很关键-value@andesta.erfan你看到的是JSON,这不是Swift字典的打印方式,所以现在它不是“键值”,它只是一个JSON字符串。值肯定是一个字符串。似乎字符串是JSON,您必须单独反序列化它(您实际使用
Mapper
对象所做的操作)好的。但是“它只是一个JSON字符串”是什么意思?我怎样才能让[String:Any]读到我对你问题的评论。JSON只是一种表示。JSON中的“N”代表“Notation”。这一直是新开发人员缺少的一步。序列化后的数据表示、字符串表示,最后是您自己语言表示的字典/数组。因此,当在某些JSON中出现被盗用的JSON字符串时,就像在您的例子中一样,解决它的方法总是相同的。根据错误,似乎
dict[“message”]
是一个字符串,一个JSON字符串。因此,如果让jsonstringfied=dict[“message”]作为?应该可以工作的字符串。我不使用
Mapper
,而是使用标准工具:
让jsonData=jsonStringified.data(编码:.utf8);让我们试试看?JSONSerialization.jsonObject(数据:jsonData)
在伪代码中。@Larme I',将尝试code@Larme请将您的评论作为回答。没错。感谢您更正我的
Mapper().map(JSON:response)
Mapper
是否有办法处理
(NS)数据
(NS)字符串
JSON?因为这样可以避免转换。我希望,对于更高级别的第三个lib,它确实如此。是这样吗?像
Mapper().map(JSONString:jsonStringified)
Mapper().map(JSONData:JSONData)
你在使用这个吗:?@Larme是的。我只是将jsonDict转换为[String:Any]并将其交给Mapper,它成功地给了我一个模型
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
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)
let baseResponse = Mapper<NotificationModel>().map(JSONData: jsonStringifiedData)
let baseResponse = Mapper<NotificationModel>().map(JSONString: jsonStringifiedString)