iOS应用无法保存JSON数据至本地磁盘问题求助
问题:无法将获取到的JSON数据保存到设备本地,提示目录不存在
我在应用里写了获取服务器JSON数据的代码:
struct ServerConnect { enum Result<T> { case succes(T) case error(String) } typealias completionHandler = (Result<Data>) -> () func getJsonFromServer(parameters: String, completion: @escaping completionHandler) { let fullUrlString = ApiConstans.fullPath + parameters guard let url = URL(string: fullUrlString) else { debugPrint("\(ErrorsLabels.ServerConnect01)") return completion(.error("\(ErrorsLabels.ServerConnect01)")) } URLSession.shared.dataTask(with: url) { (data, response, error) in guard error == nil else { debugPrint("\(ErrorsLabels.ServerConnect02)") return completion(.error("\(ErrorsLabels.ServerConnect02)")) } guard let data = data else { debugPrint("\(ErrorsLabels.ServerConnect03)") return completion(.error("\(ErrorsLabels.ServerConnect03)")) } debugPrint("R> \(fullUrlString)") return completion(.succes(data)) }.resume() } func getJsonProducts(lang: String?, region: Int?, completion: @escaping completionHandler) { self.getJsonFromServer(parameters: "?action=GET_PRODUCTS&lang=\(lang!)®ion=\(region!)", completion: completion) } }
之后尝试把数据保存到本地:
let cms = ServerConnect() cms.getJsonProducts(lang: selectedLanguage, region: selectedRegion , completion: { (data) in switch data { case .succes(let data): self.saveJsonFileToTheDisk(path: selectedLanguage + "/json/temp.json", downloadData: data) case .error(let error): self.errorLoginMessage(txt: "\(ErrorsLabels.MainViewControler01). \(error)", title: "Blad".localized()) break } }) func saveJsonFileToTheDisk(path: String, downloadData: Data){ do { let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! let fileURL = documentsURL.appendingPathComponent(path) try downloadData.write(to: fileURL, options: .atomic) } catch { self.errorLoginMessage(txt: "\(ErrorsLabels.MainViewControler02). \(error)", title: "Blad".localized()) } }
但保存失败,错误提示:
"目录temp.json不存在。UserInfo=PNSFilePath=Users/mymac/Library/Developer........./json/temp.json. .... 没有该文件或目录"
请问问题出在哪里?
解决方案:提前创建文件的父目录
嗨,这个问题很常见~你遇到的核心问题是:当你尝试写入文件到包含子目录的路径时,FileManager的write(to:)方法不会自动帮你创建那些不存在的父目录。比如你要保存到selectedLanguage/json/temp.json,但selectedLanguage文件夹和json文件夹都还没被创建,所以系统会报错说目录不存在。
修改你的saveJsonFileToTheDisk函数,在写入文件之前先创建所有必要的父目录就可以解决了:
func saveJsonFileToTheDisk(path: String, downloadData: Data){ do { let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! let fileURL = documentsURL.appendingPathComponent(path) // 获取文件的父目录URL let parentDirectory = fileURL.deletingLastPathComponent() // 创建父目录(包括所有不存在的中间目录),如果已经存在就不会报错 try FileManager.default.createDirectory(at: parentDirectory, withIntermediateDirectories: true, attributes: nil) // 现在再写入文件 try downloadData.write(to: fileURL, options: .atomic) } catch { self.errorLoginMessage(txt: "\(ErrorsLabels.MainViewControler02). \(error)", title: "Blad".localized()) } }
关键的变化是这两行:
let parentDirectory = fileURL.deletingLastPathComponent():拿到要保存文件的父目录(也就是selectedLanguage/json这个路径)try FileManager.default.createDirectory(at: parentDirectory, withIntermediateDirectories: true, attributes: nil):withIntermediateDirectories: true参数会自动创建所有不存在的中间目录,不管是selectedLanguage还是里面的json文件夹,都会被创建出来。
另外还有个小建议:你代码里的succes拼写错了,应该是success,虽然不影响功能,但统一拼写会让代码更规范哦~
内容的提问来源于stack exchange,提问作者triff
相关产品推荐
相关产品推荐

