how to set and later get array of json objects in UserDefaults
?
My application crashes when i try to set it as follow:
import SwiftyJSON
var finalArray = [JSON]()
UserDefaults.standard.set(finalArray, forKey: "attemptedArray")
my data looks like:
[{
"marked" : 3,
"attempted" : true,
"correct" : 3,
"subject" : 1,
"status" : true,
"question" : 219,
"answer" : 32931,
"time" : 15,
"score" : 5,
"chapter" : 26
}, {
"marked" : 4,
"attempted" : true,
"correct" : 4,
"subject" : 1,
"status" : true,
"question" : 550,
"answer" : 34256,
"time" : 23,
"score" : 10,
"chapter" : 26
}, {
"marked" : 1,
"attempted" : true,
"correct" : 1,
"subject" : 1,
"status" : true,
"question" : 566,
"answer" : 34317,
"time" : 33,
"score" : 14,
"chapter" : 26
}]
UserDefaults
can't save SwiftyJSON's JSON
type. You have to save some type which they supports, in this case, you're looking for Data
.
Anyway, for saving Data
to UserDefaults
aren't the best and you should save your Data
to file somewhere else. To achieve this, you can use FileManager
.
So, create custom model for your data instead of using JSON
and adopt Codable
to your custom model
struct Model: Codable {
var marked, correct, subject, question, answer, time, score, chapter: Int
var attempted, status: Bool
}
Then you should use this Model
as type of element inside your array (note that then you'll need to decode your response from Data
using JSONDecoder
(see below))
var finalArray = [Model]()
then you can use JSONEncoder
for encoding your array of models to Data
which you can write to some file
do {
let encoded = try JSONEncoder().encode(finalArray)
let preferencesDirectoryURL = FileManager.default.urls(for: .libraryDirectory, in: .userDomainMask).first!.appendingPathComponent("Preferences", isDirectory: true)
let fileURL = preferencesDirectoryURL.appendingPathComponent("fileName.json")
try encoded.write(to: fileURL)
} catch { print(error) }
and JSONDecoder
for decoding Data
from saved file
do {
let preferencesDirectoryURL = FileManager.default.urls(for: .libraryDirectory, in: .userDomainMask).first!.appendingPathComponent("Preferences", isDirectory: true)
let fileURL = preferencesDirectoryURL.appendingPathComponent("fileName.json")
if let data = try? Data(contentsOf: fileURL) {
let decoded = try JSONDecoder().decode([Model].self, from: data)
}
} catch { print(error) }
do{
try let data = NSKeyedArchiver.archivedData(withRootObject: finalArray, requiringSecureCoding: false)
UserDefaults.standard.set(data, forKey: "attemptedArray")
}catch{
print("Print exception here")
}
Saving a lot of data in the NSuser defaults isn't recommended for some reasons:
If you will delete some of the cells of the array you will need to delete them from the nsuser defaults. It will be easy only if you save them as an array and not as individuals.
If you choose to save them as array every time you will delete or add one item you will need to save all of them. It can take slot of time if the array is big
Anyone can access the NSuser defaults. So it isn't safe
Anyway I really recommend using core data. It saves you all the troubles I mentioned.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.