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

Swift 4 iOS:Bundle中本地JSON文件无法写入的问题求助

为什么你无法写入Bundle里的JSON文件?

嘿,这个问题我碰到过好多次啦!你之所以写操作失败,核心原因是App的主Bundle是只读的——苹果为了保障App的完整性和安全性,不允许直接修改Bundle内的任何资源文件,哪怕你拿到了它的URL也没用。

那该怎么解决呢?我们需要把JSON文件复制到App的可读写沙盒目录里(比如Documents目录),之后所有的读写操作都针对这个复制后的文件来做。

完整解决方案步骤

1. 获取可读写的文件URL

先定义一个方法,用来获取Documents目录下的目标文件路径:

func getWritableCategoriesFileURL() -> URL? {
    // 获取Documents目录的URL
    guard let documentsDir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else {
        return nil
    }
    // 拼接目标文件的完整URL
    return documentsDir.appendingPathComponent("categories.json")
}

2. 初始化:把Bundle文件复制到Documents(仅第一次执行)

在App启动或者首次操作文件时,检查Documents里是否已有该文件,如果没有就从Bundle复制过去:

func copyBundleFileToDocumentsIfNeeded() {
    guard let bundleFileURL = Bundle.main.url(forResource: "categories", withExtension: "json"),
          let writableFileURL = getWritableCategoriesFileURL() else {
        return
    }
    
    // 检查Documents目录是否已存在目标文件
    if !FileManager.default.fileExists(atPath: writableFileURL.path) {
        do {
            // 执行复制操作
            try FileManager.default.copyItem(at: bundleFileURL, to: writableFileURL)
            print("文件已成功复制到Documents目录")
        } catch {
            print("复制文件失败:\(error.localizedDescription)")
        }
    }
}

3. 修改读取逻辑:从Documents目录读取

把原来读取Bundle文件的代码,改成读取Documents里的可写文件:

func readCategories() -> Any? {
    guard let writableFileURL = getWritableCategoriesFileURL(),
          let data = try? Data(contentsOf: writableFileURL) else {
        return nil
    }
    do {
        let json = try JSONSerialization.jsonObject(with: data, options: [])
        return json
    } catch {
        print("读取JSON失败:\(error.localizedDescription)")
        return nil
    }
}

4. 修改写入逻辑:写入到Documents目录

现在你的写入操作就能正常执行了,替换掉原来指向Bundle的URL:

func writeCategories(_ categories: [YourCategoryModel]) {
    guard let writableFileURL = getWritableCategoriesFileURL() else {
        return
    }
    
    let dict = ["data": categories.compactMap { $0.dictionary }]
    do {
        // 加.prettyPrinted可以让生成的JSON格式更美观,方便调试
        let jsonData = try JSONSerialization.data(withJSONObject: dict, options: [.prettyPrinted])
        try jsonData.write(to: writableFileURL)
        print("JSON写入成功!")
    } catch {
        print("写入JSON失败:\(error.localizedDescription)")
    }
}

额外提示

  • 记得在App启动时调用copyBundleFileToDocumentsIfNeeded(),比如在AppDelegate的didFinishLaunchingWithOptions里,或者SceneDelegate的scene(_:willConnectTo:options:)方法中。
  • 如果需要查看Documents目录里的文件,可以通过Xcode的Window > Devices and Simulators,选中你的App,点击Download Container导出沙盒文件进行查看。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 07:57:08