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

无法更新cacheDirectory中JSON数据,GitHub更新后本地缓存未同步

问题解决:本地缓存JSON无法自动同步GitHub更新数据

核心问题分析

你的代码存在三个关键问题导致无法自动加载最新JSON:

  • 异步任务执行顺序错误:初始化时先启动异步的downloadJSON,立刻同步读取本地缓存,此时下载还未完成,加载的始终是旧数据。
  • 下载完成后未更新数据源:即使新JSON下载成功,也没有重新读取文件并更新allSongs,只有重启时才会重新读取。
  • URLSession默认缓存:默认情况下URLSession会缓存请求结果,即使GitHub上的JSON更新了,依然可能拿到旧的缓存响应。

修复后的完整代码

class FetchingJSONFile5 {
    @Published var allSongs: [TuunoLabu] = []
    @Published var isNewFile: Bool = true
    let folderOne = "TuunoLabu_Folder1"

    init() {
        createFolderOne()
        // 先加载本地缓存保证离线可用,再启动下载任务更新最新数据
        if let lyrics = fetchTuunoLabu(from: "TuunoLabu") {
            allSongs = lyrics
        }
        downloadJSON()
    }

    private func createFolderOne() {
        guard let directoryOne = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first?.appendingPathComponent(folderOne).relativePath else { return }
        
        if !FileManager.default.fileExists(atPath: directoryOne) {
            do {
                try FileManager.default.createDirectory(atPath: directoryOne, withIntermediateDirectories: true)
                print("Successfully created Folder One")
            } catch let error {
                print("Error while creating Folder One", error)
            }
        }
    }

    private func downloadJSON() {
        guard let url = URL(string: "https://raw.githubusercontent.com/siantung/TuunoLabu/fac87c9d6b63f5e52cadb8873fb0d77cd0fc91e1/JSON/TuunoLabu.json") else {
            print("ERROR: Could not find the URL")
            return
        }
        
        // 构建请求,禁用本地缓存,确保获取最新数据
        var urlRequest = URLRequest(url: url)
        urlRequest.cachePolicy = .reloadIgnoringLocalCacheData
        
        guard let directory = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask)
            .first?.appendingPathComponent(folderOne)
            .appendingPathComponent("TuunoLabu.json") else { return }
        
        let dataTask = URLSession.shared.dataTask(with: urlRequest) { [weak self] data, response, error in
            guard let data = data, error == nil else {
                print("Download error: \(error?.localizedDescription ?? "Unknown error")")
                self?.isNewFile = false
                return
            }
            
            // 验证响应状态码,避免错误响应覆盖本地缓存
            guard let httpResponse = response as? HTTPURLResponse, (200...299).contains(httpResponse.statusCode) else {
                print("Invalid response status code")
                self?.isNewFile = false
                return
            }
            
            do {
                try data.write(to: directory, options: .atomic)
                print("Successfully saved downloaded JSON new file.")
                // 下载完成后,在主队列更新数据源(@Published属性必须在主线程修改)
                if let lyrics = self?.fetchTuunoLabu(from: "TuunoLabu") {
                    DispatchQueue.main.async {
                        self?.allSongs = lyrics
                        self?.isNewFile = true
                    }
                }
            } catch let error {
                print("Error saving file: ",error)
                self?.isNewFile = false
            }
        }
        dataTask.resume()
    }

    private func fetchTuunoLabu(from name: String) -> [TuunoLabu]? {
        guard let directoryOne = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask)
            .first?.appendingPathComponent(folderOne)
            .appendingPathComponent("TuunoLabu.json") else {
            print("Error to retrieve directory while fetching file")
            return nil
        }

        if FileManager.default.fileExists(atPath: directoryOne.relativePath) {
            do {
                let data = try Data(contentsOf: directoryOne)
                return try JSONDecoder().decode([TuunoLabu].self, from: data)
            } catch {
                print("Error JSON decoding: \(error)")
            }
        }
        return nil
    }
}

关键修改点说明

  • 调整初始化逻辑:优先加载本地缓存保证离线用户正常使用,再触发下载任务拉取最新数据。
  • 强制跳过本地缓存:通过设置urlRequest.cachePolicy = .reloadIgnoringLocalCacheData,确保每次请求都从GitHub获取最新JSON。
  • 下载完成后实时更新数据:文件写入成功后,重新读取本地文件并在主队列更新allSongs,保证UI能实时刷新最新内容。
  • 增加响应校验:验证HTTP状态码,避免错误的响应内容覆盖本地有效缓存。

进阶优化建议

如果想减少不必要的网络请求,可以:

  • 记录本地文件的Last-Modified时间,请求时通过If-Modified-Since请求头询问服务器是否有更新,仅当文件变更时才下载。
  • 存储GitHub返回的ETag值,对比本地ETag,只有不一致时才执行下载操作。

内容的提问来源于stack exchange,提问作者Lian

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 09:52:50