如何替换Bundle中已打包文件内容?为何修改未生效?
嘿,这个坑我之前也踩过!核心原因其实很直白:App的主Bundle是只读的。当你的App安装到设备或模拟器后,系统会把Bundle里的所有资源文件保护起来,不允许直接修改。你的代码看起来没抛出错误,大概率是因为系统悄悄拦截了写入操作,或者你写入的其实是一个临时副本,根本没碰到底层的原文件。
下面是具体的解决步骤:
1. 先把Bundle里的JSON文件复制到可读写的目录
App的Documents目录是系统允许我们自由读写的区域,所以第一步要做的是把初始的shared.json从Bundle复制到这里(只需要做一次,比如App首次启动时):
// 获取Documents目录的URL func getDocumentsDirectory() -> URL { let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask) return paths[0] } // 处理文件复制逻辑 let bundleJsonURL = Bundle.main.url(forResource: "shared", withExtension: "json")! let targetJsonURL = getDocumentsDirectory().appendingPathComponent("shared.json") // 如果Documents里还没有这个文件,就从Bundle复制过去 if !FileManager.default.fileExists(atPath: targetJsonURL.path) { do { try FileManager.default.copyItem(at: bundleJsonURL, to: targetJsonURL) print("初始文件已复制到Documents目录") } catch { print("复制初始文件失败:\(error.localizedDescription)") } }
2. 所有读写操作都针对Documents里的文件
把你原来的代码里的fileUrl替换成上面的targetJsonURL,之后的读写就都能生效了:
do { // 写入数据到Documents目录的文件 try jsonData.write(to: targetJsonURL, atomically: true, encoding: .utf8) // 验证写入结果 let newData = try String(contentsOf: targetJsonURL, encoding: .utf8) print("更新后的文件内容:\(newData)") } catch { print("文件操作失败:\(error.localizedDescription)") }
补充说明:为什么之前的代码没报错?
有些情况下,系统会允许你写入Bundle路径,但实际上是写入到了一个临时的沙箱副本里——你当时读取的时候能看到修改后的内容,但原Bundle文件根本没变化,等App重启后,一切又会回到初始状态。所以一定要把文件放到可读写的目录里操作才行。
内容的提问来源于stack exchange,提问作者Darrell Brogdon




