【问题标题】:Could not cast value of type '__NSDictionaryI'无法转换类型“__NSDictionaryI”的值
【发布时间】:2021-09-27 14:39:52
【问题描述】:

我正在使用此代码来调用我的 REST Web 服务。 但是,如果我尝试解码 Web 服务调用的结果,则会收到错误消息。

class func callPostServiceReturnJson(apiUrl urlString: String, parameters params : [String: AnyObject]?,  parentViewController parentVC: UIViewController, successBlock success : @escaping ( _ responseData : AnyObject, _  message: String) -> Void, failureBlock failure: @escaping (_ error: Error) -> Void) {
        
        if Utility.checkNetworkConnectivityWithDisplayAlert(isShowAlert: true) {
            var strMainUrl:String! = urlString + "?"

            for dicd in params! {
                strMainUrl.append("\(dicd.key)=\(dicd.value)&")
            }
            print("Print Rest API : \(strMainUrl ?? "")")


            let manager = Alamofire.SessionManager.default
            manager.session.configuration.timeoutIntervalForRequest = 120
            manager.request(urlString, method: .get, parameters: params)
                .responseJSON {
                    response in
                    switch (response.result) {
                    case .success:
                        do{
                                            
                                        
                            let users = try JSONDecoder().decode(OrderStore.self, from: response.result.value! as! Data)
                            
                        }catch{
                            print("errore durante la decodifica dei dati: \(error)")
                        }
                        if((response.result.value) != nil) {
                            success(response as AnyObject, "Successfull")
                        }
                        break
                    case .failure(let error):
                        print(error)
                        if error._code == NSURLErrorTimedOut {
                            //HANDLE TIMEOUT HERE
                            print(error.localizedDescription)
                            failure(error)
                        } else {
                            print("\n\nAuth request failed with error:\n \(error)")
                            failure(error)
                        }
                        break
                    }
            }
        } else {
            parentVC.hideProgressBar();
            Utility.showAlertMessage(withTitle: EMPTY_STRING, message: NETWORK_ERROR_MSG, delegate: nil, parentViewController: parentVC)
        }
    }

这是我可以打印的错误:

Could not cast value of type '__NSDictionaryI' (0x7fff86d70b80) to 'NSData' (0x7fff86d711e8).
2021-09-27 16:34:49.810245+0200 ArrivaArrivaStore[15017:380373] Could not cast value of type '__NSDictionaryI' (0x7fff86d70b80) to 'NSData' (0x7fff86d711e8).
Could not cast value of type '__NSDictionaryI' (0x7fff86d70b80) to 'NSData' (0x7fff86d711e8).
CoreSimulator 732.18.6 - Device: iPhone 8 (6F09ED5B-8607-4E47-8E2E-A89243B9BA90) - Runtime: iOS 14.4 (18D46) - DeviceType: iPhone 8

我从https://app.quicktype.io/ 生成了 OrderStore.swift 类

//编辑

【问题讨论】:

  • 嗯,你明白错误了吗?
  • 是的,但我不知道该如何解决
  • 这意味着response.result.valueDictionary,而不是Data,如果这确实是导致崩溃的行(给出它会有所帮助)。你使用responseJSON{},所以response.result.value 是字典或数组,因为JSONSerialization 已经被调用了。如果我没记错的话,请使用response.result.data。如果可行,则使用允许直接解码到 Codable 结构的 Alamofire 方法(避免对 JSONSerialization 的不必要调用)。

标签: json swift decode


【解决方案1】:

.responseJSON 返回反序列化的 JSON,在本例中为 Dictionary。它不能转换为 Data 错误明确确认的内容。

要获取原始数据,您必须指定.responseData

替换

.responseJSON {
      response in
         switch (response.result) {
            case .success:
                    do {
                       let users = try JSONDecoder().decode(OrderStore.self, from: response.result.value! as! Data)
 

.responseData {
      response in
         switch response.result {
            case .success(let data):
                    do {
                       let users = try JSONDecoder().decode(OrderStore.self, from: data)

考虑到 AF 5 甚至支持 .responseDecodable 直接解码到模型中

.responseDecodable {
      (response : DataResponse<OrderStore,AFError>) in
         switch response.result {
            case .success(let users): print(users)

旁注:

  • 正如您在上一个问题中提到的,AF API 中没有 AnyObject。参数为[String:Any]responseData是解码后的类型。我建议将函数设为通用并使用方便的Result 类型。

  • 删除break 语句。这是斯威夫特。

【讨论】:

  • 感谢您的回答,但错误是一样的。我在我的问题中添加了(让数据)的类型
  • 如果您完全按照建议替换代码,则不会发生同样的错误
  • 我正在使用您的代码 .respondeData 但这是现在的错误:errore durante la decodifica dei dati: typeMismatch(ArrivaArrivaStore.JSONNull, Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "result ", intValue: nil), _JSONKey(stringValue: "Index 1", intValue: 1), CodingKeys(stringValue: "time_booking", intValue: nil)], debugDescription: "JSONNull 的类型错误",底层错误: nil))
  • 这是一个不同的错误,一个 DecodingError。它说在数组result 的第二项中,属性time_booking 的类型是错误的。
  • time_booking 不是强制的,jason 可以包含这个字段,不能包含这个。在我的 OrderStore.swift 类中是这样声明的: let timeBooking: JSONNull?
【解决方案2】:

这是 Vadian 答案的附录。我试图说明导致您陷入此错误的过程,希望您将来能在它导致您误入歧途之前注意到它

这是一种很常见的错误“模式”。

想象一下,您正在穿越迷宫,从某种初始数据格式开始,并尝试到达某种目标数据格式。在此过程中的每一点,都有多个选项可供选择,有些可以让您更接近目标,有些可以让您更远。

您选择在名为responseJSON 的入口处进入迷宫,其回调将为您提供AFDownloadResponse&lt;Any&gt;(这是您称为response 的变量的推断类型)。

JSON 结构的顶层总是有一个数组或字典。由于 Alamofire 无法静态知道您将处理哪种 JSON,因此它使用 Any 对其进行建模。在运行时,Value 的类型将是 NSDictionary(或其具体子类之一,如 __NSDictionaryI)或 NSArray(或其具体子类之一)。

然后您决定获取该responseresult。它的静态类型是Result&lt;Any, Error&gt;。您 switch 处理此错误,确保您处理的是 success 案例而不是 failure 案例。莫名其妙地,您忽略了与成功相关的有效负载值,但后来用result.response.value! 强制解包。

result.response.value 是一个Any,但是为了安抚编译器,你将它强制转换为Data。但我们已经知道这只会是NSArrayNSDictionary,所以这永远不会起作用。

您可以在迷宫的这个区域继续徘徊,然后通过漫长的路径跌跌撞撞地到达最终​​目标。例如,您可以强制转换为 NSDictionary,然后将该字典结构重新序列化回 JSON 字符串,您可以将其转换为 Data,然后将其传递给 JSONDecoder().decode,然后它将解码那个 JSON 回来了。当然,这都是非常迂回和浪费的。问题是 responseJSON 迷宫入口不适合您要去的地方!

您本可以进入responseData 迷宫入口,这会让您直接到达Data 目的地!

虽然你可能会意识到Data 一直是一个红鲱鱼。你实际上并不想要Data。您想解码OrderStore,而Data 是您认为需要到达那里的方式。但事实证明,有很多人通过Data 入口进入,目的是解码一些 JSON,Alamofire 人专门为你开辟了一个新入口:responseDecodable。它会将您正确带到OrderStore,并在您不必担心它的引擎盖下摆弄 JSON、Data 或其他任何东西。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-11-02
    • 2016-03-05
    • 2023-03-20
    • 2015-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多