I found a weird behavior when using UserDefaults to save/load data, what I do as below.
Well, it is a random issue that I check my code but didn't found clues. My data model is very simple, so it should be saved and load quickly. Would you gives me some hint/advice?
class Note: Codable {
var content: String
init(content: String) {
self.content = content
}
}
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
...
var notes = [Note]()
override func viewDidLoad() {
super.viewDidLoad()
...
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
loadData()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return notes.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.accessoryType = .disclosureIndicator
let node = notes[indexPath.row].content
cell.textLabel?.text = node
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let vc = DetailViewController()
vc.bodyText = notes[indexPath.row].content
navigationController?.pushViewController(vc, animated: true)
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
notes.remove(at: indexPath.row)
print("notes: \(notes)")
saveData()
tableView.deleteRows(at: [indexPath], with: .fade)
count = notes.count
}
}
@objc func createNewNote() {
let vc = NewNoteViewController()
vc.notes = notes
navigationController?.pushViewController(vc, animated: true)
}
func loadData() {
DispatchQueue.global().async { [weak self] in
let defaults = UserDefaults.standard
if let savedNotes = defaults.object(forKey: "notes") as? Data {
let jsonDecoder = JSONDecoder()
do {
self?.notes = try jsonDecoder.decode([Note].self, from: savedNotes)
print("Load notes: \(String(describing: self?.notes))")
DispatchQueue.main.async {
self?.tableView.reloadData()
self?.count = self?.notes.count ?? 0
}
} catch {
print("Failed to load notes")
}
}
}
}
func saveData() {
DispatchQueue.global().async { [weak self] in
let jsonEncoder = JSONEncoder()
if let savedData = try? jsonEncoder.encode(self?.notes) {
let defaults = UserDefaults.standard
defaults.set(savedData, forKey: "notes")
print("value saved")
} else {
print("Failed to save notes")
}
}
}
}
UserDefaults
doesn't write the data to disk immediately, it waits to perform batch writes for performance reasons.
If you're re-launching the app through Xcode it might be killing the app before it has the chance to persist the changes.
Try force closing the app on the device instead of re-launching with Xcode, or just wait a few more seconds before re-launching and this shouldn't happen.
To be clear, what you're seeing is not an issue, it's a side-effect of the way you're launching the app. Don't worry about it, it won't affect the way your app works once it's installed.