无法转换类型“__NSDictionaryI”的值

Could not cast value of type '__NSDictionaryI'

我正在使用此代码调用我的其余 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 class

//编辑

.responseJSON returns 反序列化 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语句。这是 Swift.

这是对 Vadian 回答的补充。我正在尝试说明导致您出现此错误的过程,希望您将来能在它误入歧途之前注意到它

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

把它想象成您正在穿越迷宫,从某种初始数据格式开始,并尝试到达某种目标数据格式。在沿途的每个点,都有多种选择可供选择,有些会让您更接近目标,有些会让您离目标更远。

您已选择在名为 responseJSON 的入口处进入迷宫,其回调将为您提供 AFDownloadResponse<Any>(这是您调用的变量的推断类型 response ).

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

然后您决定获取 responseresult。它的静态类型是Result<Any, Error>。你 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 或其他任何东西担心它。