Search code examples
jsonswiftdecode

Could not cast value of type '__NSDictionaryI'


I m using this code to call my rest web service. But if I try to decode the result of web service call I received error.

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)
        }
    }

This is the error that I can print:

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

I generated OrderStore.swift class from https://app.quicktype.io/

//EDIT enter image description here


Solution

  • .responseJSON returns deserialized JSON, in this case a Dictionary. It cannot be cast to Data what the error clearly confirms.

    To get the raw data you have to specify .responseData

    Replace

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

    with

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

    Consider that AF 5 supports even .responseDecodable to decode directly into the model

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

    Side notes:

    • As mentioned in your previous question there is no AnyObject in the AF API. The parameters are [String:Any] and responseData is the decoded type. I recommend to make the function generic and use the convenient Result type.

    • Delete the break statements. This is Swift.