admin管理员组文章数量:1391937
I want to write data to a custom JSON file, but it doesn't seem to load properly. The save function seems to work partially when I call it, but it looks like either it rewrites the file with only the newly saved data rather than the whole array of the json data + the new one, or there is a problem in my load function.
func loadCustomCadences(filename fileName: String) -> [Cadence] {
var cadences = [Cadence]()
if let url = Bundle.main.url(forResource: fileName, withExtension: "json") {
do {
let data = try Data(contentsOf: url)
cadences = try JSONDecoder().decode([Cadence].self, from: data)
return cadences
} catch {
print("error:\(error)")
}
}
return cadences
}
func saveCadences(_ cadence: Cadence) {
loadedCadences = loadCustomCadences(filename: "customCadences")
print("loa", loadedCadences)
do {
loadedCadences.append(cadence)
print("loazeaz", loadedCadences)
let data = try JSONEncoder().encode(loadedCadences)
let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
let fileURL = documentsDirectory.appendingPathComponent("customCadences.json")
try data.write(to: fileURL)
let jsonF = NSString(data: data, encoding: String.Encoding.utf8.rawValue)
print(jsonF ?? "zerzer")
} catch {
print("Error saving JSON: \(error)")
}
}
The first print always returns an empty array despite loading from the same file I've just saved to, while the others respectively return the data I'm trying to save and its json entry, but nothing is ever appended when I'm saving the new data, it only loads and empty array and rewrites the file with only the latest data.
Any idea how to solve this ?
I want to write data to a custom JSON file, but it doesn't seem to load properly. The save function seems to work partially when I call it, but it looks like either it rewrites the file with only the newly saved data rather than the whole array of the json data + the new one, or there is a problem in my load function.
func loadCustomCadences(filename fileName: String) -> [Cadence] {
var cadences = [Cadence]()
if let url = Bundle.main.url(forResource: fileName, withExtension: "json") {
do {
let data = try Data(contentsOf: url)
cadences = try JSONDecoder().decode([Cadence].self, from: data)
return cadences
} catch {
print("error:\(error)")
}
}
return cadences
}
func saveCadences(_ cadence: Cadence) {
loadedCadences = loadCustomCadences(filename: "customCadences")
print("loa", loadedCadences)
do {
loadedCadences.append(cadence)
print("loazeaz", loadedCadences)
let data = try JSONEncoder().encode(loadedCadences)
let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
let fileURL = documentsDirectory.appendingPathComponent("customCadences.json")
try data.write(to: fileURL)
let jsonF = NSString(data: data, encoding: String.Encoding.utf8.rawValue)
print(jsonF ?? "zerzer")
} catch {
print("Error saving JSON: \(error)")
}
}
The first print always returns an empty array despite loading from the same file I've just saved to, while the others respectively return the data I'm trying to save and its json entry, but nothing is ever appended when I'm saving the new data, it only loads and empty array and rewrites the file with only the latest data.
Any idea how to solve this ?
Share Improve this question asked Mar 13 at 2:42 JulienMJulienM 491 gold badge3 silver badges11 bronze badges 6 | Show 1 more comment2 Answers
Reset to default 1Your assumption in "The first print always returns an empty array despite loading from the same file I've just saved to, ..." is not correct. You are reading from a file in the
Bundle.main.url(forResource: ...)
, but you are writing to a different file, let fileURL = documentsDirectory.appendingPathComponent("customCadences.json")
.
To read and write to the same file, try this approach using the same file and directory you save the json data to:
func loadCustomCadences(filename fileName: String) -> [Cadence] {
var cadences = [Cadence]()
do {
let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
let fileURL = documentsDirectory.appendingPathComponent("customCadences.json")
let data = try Data(contentsOf: fileURL)
print("---> data: \(String(data: data, encoding: .utf8) as AnyObject)")
cadences = try JSONDecoder().decode([Cadence].self, from: data)
print("---> cadences: \(cadences)")
return cadences
} catch {
print("error:\(error)")
}
return cadences
}
func saveCadences(_ cadence: Cadence) {
var loadedCadences = loadCustomCadences(filename: "customCadences")
print("---> loa", loadedCadences)
do {
loadedCadences.append(cadence)
print("loazeaz", loadedCadences)
let data = try JSONEncoder().encode(loadedCadences)
let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
let fileURL = documentsDirectory.appendingPathComponent("customCadences.json")
try data.write(to: fileURL)
let jsonF = String(data: data, encoding: .utf8)
print("---> jsonF: \(jsonF)")
} catch {
print("Error saving JSON: \(error)")
}
}
The main reason is you're confusing between:
Bundle.main.url
: load the resources from your app bundle (your project folder)FileManager.default
: handle files and directories, even with iCloud.
And from your comments, I believe should use FileManager.default
only. I could refactor the code as below:
//Define the directory
private var cadencesDirectory: URL? {
FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
.first?
.appendingPathComponent("customCadences")
.appendingPathExtension("json")
}
//Check whenever need to create the directory
private func checkValidDirectoryAndCreateIfNeeded() {
guard let cadencesDirectory else { return }
guard !FileManager.default.fileExists(atPath: cadencesDirectory.path) else { return }
do {
try FileManager.default.createDirectory(at: cadencesDirectory, withIntermediateDirectories: true)
} catch {
print("Cannot create the directory")
}
}
func load() -> [Cadence] {
checkValidDirectoryAndCreateIfNeeded()
if let path = cadencesDirectory?.path {
let data = FileManager.default.contents(atPath: path)
//TODO: JSONDecoder or whatever here
}
}
func save() {
...
checkValidDirectoryAndCreateIfNeeded()
if let cadencesDirectory {
...
data.write(to: cadencesDirectory)
}
}
本文标签: swiftLoading and saving JSON filesStack Overflow
版权声明:本文标题:swift - Loading and saving JSON files - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744721811a2621738.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
. documentDirectory
, right? – sonle Commented Mar 13 at 3:19.documentDirectory
. Is it correct? – sonle Commented Mar 13 at 3:40loadCustomCadences
instead of usingif let url = Bundle.main.url(forResource: fileName, withExtension: "json")
use the same directory you use for saving the data, that is inside thedo
,let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! let fileURL = documentsDirectory.appendingPathComponent("customCadences.json")
. Note noif let
. – workingdog support Ukraine Commented Mar 13 at 4:29