Data Persistence in SwiftUI

Jun 20 2024 · Swift 5.9, iOS 17.2, Xcode 15.1

Lesson 02: Persisting Data in JSON Format

Demo

Episode complete

Play next episode

Next

Heads up... You’re accessing parts of this content for free, with some sections shown as obfuscated text.

Heads up... You’re accessing parts of this content for free, with some sections shown as obfuscated text.

Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.

Unlock now

Writing Data in JSON Format

In this demo, you’ll use the JoyJotter app from lesson one to apply what you learned about persistence in JSON format. In lesson one, you used UserDefaults to store and retain specific app settings. Now, your goal is to persist the entire collection of jokes. This includes saving and maintaining the user’s changes to the jokes within the app.

func writeDataOf(jokes: [Joke]) {
  do {
    // 1
    let fileURL = try FileManager.default
      .url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
      .appendingPathComponent("savedJokes.json")
    print("Document Directory Path:", fileURL.path)

    // 2
    if FileManager.default.fileExists(atPath: fileURL.path) {
      try FileManager.default.removeItem(at: fileURL)
    }

    // 3
    try JSONEncoder().encode(jokes).write(to: fileURL)
    print("Data written successfully.")
  } catch {
    print("Error writing Jokes: \(error.localizedDescription)")
  }
}
let notificationCenter = NotificationCenter.default
notificationCenter.addObserver(
  self,
  selector: #selector(appMovedToBackground),
  name: UIApplication.willResignActiveNotification,
  object: nil
)
@objc func appMovedToBackground() {
  print("App moved to background")
  writeDataOf(jokes: jokes)
}
cd ~/Library/Developer/CoreSimulator/Devices/{YOUR_SIMULATOR_UDID}/data/Containers/Data/Application/{APP_CONTAINER_UDID}/Documents

Reading Data

Open JoyJotterVM. Then, add the readDataOfJokes method to read the jokes from the Document directory.

static func readDataOfJokes() -> [Joke]? {
  do {
    // 1
    let fileURL = try FileManager.default
      .url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
      .appendingPathComponent("savedJokes.json")

    // 2
    if FileManager.default.fileExists(atPath: fileURL.path) {
      let data = try Data(contentsOf: fileURL)
      let jokes = try JSONDecoder().decode([Joke].self, from: data)
      print("Data read successfully.")
      return jokes
    } else {
      print("No jokes found at path:", fileURL.path)
      return nil
    }
  } catch {
    print("Error reading Jokes: \(error.localizedDescription)")
    return nil
  }
}
@StateObject private var joyJotterVM = JoyJotterVM(jokes: JoyJotterVM.readDataOfJokes() ?? JoyJotterVM.basicJokes)
See forum comments
Cinema mode Download course materials from Github
Previous: Instruction Next: Conclusion