You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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!)&region=\(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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 07:23:23