我正在尝试制作一个 iOS 应用程序,我必须保存一个 JSON 文件,但我收到此错误:
Landmarks/ModelData.swift:45:致命错误:无法写入 /private/var/containers/Bundle/Application/.../Landmarks.app/landmarkData.json: 错误域=NSCocoaErrorDomain代码=513“您无权将文件“landmarkData.json”保存在“Landmarks”文件夹中。”
但是,这只发生在我的 iPhone 11 上测试应用程序时,在模拟器上运行应用程序时,它按预期工作。
这是我正在使用的保存功能:
func save(_ landmarks: [Landmark]) {
let encoder = JSONEncoder()
do {
let data = try encoder.encode(landmarks)
let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
let fileURL = documentsDirectory.appendingPathComponent("landmarkData.json")
guard let file = Bundle.main.url(forResource: "landmarkData.json", withExtension: nil)
else {
fatalError("Couldn't find landmarkData.json in main bundle.")
}
do {
try data.write(to: file)
} catch {
fatalError("Couldn't write to \(file.path):\n\(error)")
}
} catch {
fatalError("Couldn't encode landmarks as JSON:\n\(error)")
}
}
我想我必须将文件保存在另一个文件夹中,例如文档文件夹,但我不确定该怎么做。
我试过这个:
import Foundation
@Observable
class ModelData {
init() {
copyFileFromBundleToDocumentsFolder(sourceFile: "landmarkData.json")
landmarks = load("landmarkData.json")
}
var landmarks: [Landmark] = []
}
func load<T: Decodable>(_ filename: String) -> T {
let data: Data
let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
let fileURL = documentsURL.appendingPathComponent(filename)
do {
data = try Data(contentsOf: fileURL)
} catch {
fatalError("Couldn't find \(filename) in Documents directory:\n\(error)")
}
do {
let decoder = JSONDecoder()
return try decoder.decode(T.self, from: data)
} catch {
fatalError("Couldn't parse \(filename) as \(T.self):\n\(error)")
}
}
func save(_ landmarks: [Landmark]) {
let encoder = JSONEncoder()
do {
let data = try encoder.encode(landmarks)
let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
let fileURL = documentsURL.appendingPathComponent("landmarkData.json")
do {
try data.write(to: fileURL)
print("Successfully wrote data to \(fileURL.path)")
} catch {
fatalError("Couldn't write to \(fileURL.path):\n\(error)")
}
} catch {
fatalError("Couldn't encode landmarks as JSON:\n\(error)")
}
}
func copyFileFromBundleToDocumentsFolder(sourceFile: String) {
let fileManager = FileManager.default
let documentsURL = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first!
let destinationURL = documentsURL.appendingPathComponent(sourceFile)
if !fileManager.fileExists(atPath: destinationURL.path) {
if let sourceURL = Bundle.main.url(forResource: sourceFile, withExtension: nil) {
do {
try fileManager.copyItem(at: sourceURL, to: destinationURL)
print("\(sourceFile) copied to Documents directory.")
} catch {
print("Error copying file: \(error)")
}
} else {
print("Source file not found in bundle.")
}
}
}
但它既没有返回任何错误,也无法读取/写入文件,所以我假设它没有使用正确的路径。
提前致谢!
你说
guard let file = Bundle.main.url(forResource: "landmarkData.json", withExtension: nil)
然后你有 try data.write(to: file)
- 你正在尝试将数据写入应用程序包。您可以在模拟器上执行此操作,因为文件沙箱不是强制执行的,但在真实设备中,该捆绑包是只读的。
无论如何,这并不是您真正想要做的。您想要将其保存到
fileURL
位置:try write(to: fileURL)