iOS Swift使用Alamofire请求接口时__NSDictionaryI无法转Data报错问题
报错原因
你调用了Alamofire的responseJSON响应回调,这个方法会自动把接口返回的原始JSON Data解析成Foundation类型(字典、数组等,你本次返回的是不可变字典,对应报错里的__NSDictionaryI),所以response.result.value已经是解析后的字典对象,你强制转换成Data类型自然会触发类型转换失败的崩溃。
解决方案
提供两种可选修复方式,优先推荐方案1:
方案1:改用responseData回调拿原始数据解码
将原来的.responseJSON回调改为.responseData,直接拿到接口返回的原始二进制数据传给JSONDecoder解码即可,修改后的完整代码如下:
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 // 此处将responseJSON改为responseData manager.request(urlString, method: .get, parameters: params) .responseData { response in switch (response.result) { case .success(let data): do{ let users = try JSONDecoder().decode(OrderStore.self, from: data) // 解码成功后可按需将users对象传入success回调 }catch{ print("数据解码错误: \(error)") } if let value = response.result.value { success(value as AnyObject, "操作成功") } break case .failure(let error): print(error) if error._code == NSURLErrorTimedOut { print(error.localizedDescription) failure(error) } else { print("\n\n认证请求失败,错误信息:\n \(error)") failure(error) } break } } } else { parentVC.hideProgressBar(); Utility.showAlertMessage(withTitle: EMPTY_STRING, message: NETWORK_ERROR_MSG, delegate: nil, parentViewController: parentVC) } }
方案2:将已解析的字典转成Data再解码
如果你需要保留responseJSON回调的逻辑,可以先把拿到的字典通过JSONSerialization序列化为Data,再传给JSONDecoder解码,这种方式多了一次序列化操作,性能略低于方案1:
do { guard let jsonDic = response.result.value as? [String: Any] else { // 处理返回值不是字典的异常 return } let data = try JSONSerialization.data(withJSONObject: jsonDic) let users = try JSONDecoder().decode(OrderStore.self, from: data) } catch { print("数据解码错误: \(error)") }
额外优化提示:你代码中手动拼接GET参数生成的
strMainUrl没有被实际传入请求使用,Alamofire的request方法传入parameters参数后会自动拼接GET请求的查询参数,这段冗余的拼接代码可以直接删除。
内容的提问来源于stack exchange,提问作者bircastri
相关产品推荐
相关产品推荐

