iOS开发:网络下载数据存设备内部失败,类型转换报错求助
解决Cannot convert value of type 'ServerConnect.Result' to expected argument type 'Data'问题
这个错误的核心原因很直白:你在getJsonProducts的completion回调里拿到的参数data并不是直接的Data类型,而是你自定义的ServerConnect.Result<Data>枚举类型。你得先解析这个枚举,取出成功状态下的真实Data,再传给保存函数。
具体修改步骤:
- 在completion回调中,通过
switch或者if case判断Result的状态:- 匹配到
.success(data)时,把这个data传给保存函数 - 匹配到
.error(message)时,添加错误日志或用户提示逻辑
- 匹配到
修改后的完整代码示例:
首先先修正ServerConnect里的小细节(比如拼写错误、强制解包风险):
struct ServerConnect { enum Result<T> { case success(T) // 修正拼写错误:succes → success case error(String) } typealias CompletionHandler = (Result<Data>) -> () // 遵循Swift命名规范,首字母大写 func getJsonFromServer(parameters: String, completion: @escaping CompletionHandler) { let fullUrlString = ApiConstans.fullPath + parameters guard let url = URL(string: fullUrlString) else { let errorMsg = ErrorsLabels.ServerConnect01 debugPrint(errorMsg) return completion(.error(errorMsg)) } URLSession.shared.dataTask(with: url) { (data, response, error) in if let error = error { let errorMsg = ErrorsLabels.ServerConnect02 debugPrint("\(errorMsg): \(error.localizedDescription)") return completion(.error(errorMsg)) } guard let data = data else { let errorMsg = ErrorsLabels.ServerConnect03 debugPrint(errorMsg) return completion(.error(errorMsg)) } debugPrint("R> \(fullUrlString)") completion(.success(data)) }.resume() } func getJsonProducts(lang: String?, region: Int?, completion: @escaping CompletionHandler) { // 用可选绑定替代强制解包,避免nil崩溃 guard let lang = lang, let region = region else { debugPrint("Lang or region parameter is nil") return completion(.error("Invalid language or region")) } let parameters = "?action=GET_PRODUCTS&lang=\(lang)®ion=\(region)" self.getJsonFromServer(parameters: parameters, completion: completion) } }
然后修改调用getJsonProducts的代码,正确处理Result枚举:
getJsonProducts(lang: selectedLanguage, region: selectedRegion) { result in switch result { case .success(let data): print("@@@@@ Successfully fetched data") saveJsonFileToTheDisk(path: "\(selectedLanguage)/json/products.json", downloadData: data) case .error(let message): print("Failed to fetch data: \(message)") // 这里可以添加用户提示,比如弹出Alert告知加载失败 } } func saveJsonFileToTheDisk(path: String, downloadData: Data){ do { let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! // 先创建目标目录,避免路径不存在导致写入失败 let directoryURL = documentsURL.appendingPathComponent("\(selectedLanguage)/json") try FileManager.default.createDirectory(at: directoryURL, withIntermediateDirectories: true) let fileURL = documentsURL.appendingPathComponent(path) try downloadData.write(to: fileURL, options: .atomic) print("File saved successfully at: \(fileURL.path)") } catch { print("Failed to save file: \(error.localizedDescription)") } }
额外优化说明:
- 修正了
Result枚举的拼写错误,避免后续调用时出现不必要的bug - 替换强制解包为可选绑定,降低崩溃风险
- 在保存函数中添加了目录创建逻辑,确保保存路径的目录存在
- 补充了错误分支的日志输出,方便调试排查问题
内容的提问来源于stack exchange,提问作者triff
相关产品推荐
相关产品推荐

