SwiftUI Persistence

SwiftUI Persistence (FileManager)

When a user closes your application, any data stored in variables or arrays is permanently destroyed.

To save data between app launches, you must persist it to the device's storage drive.

One of the most fundamental ways to store custom files and raw data is by using Swift's FileManager.


The Documents Directory

Every iOS application is assigned its own private "sandbox" on the iPhone's hard drive.

Inside this sandbox is a folder called the Documents Directory, which is the perfect place to save user-generated content.

To save or read a file, you must first find the exact URL path to this directory.

Finding the Documents Directory:

import Foundation

func getDocumentsDirectory() -> URL { let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask) return paths[0] }

This function asks the file manager for the correct directory URL and returns the very first result.


Writing Data to Disk

To write data, you append a filename to the Documents directory URL to create a complete file path.

Then, you use the .write(to:options:) method available on String or Data objects.

Saving a String:

func saveMessage() {
    let message = "Hello, local storage!"
    let url = getDocumentsDirectory().appendingPathComponent("message.txt")
    do {
        // Atomic writing ensures the file is safely written before replacing the old one
        try message.write(to: url, atomically: true, encoding: .utf8)
        print("File saved successfully!")
    } catch {
        print("Failed to save file: \\(error.localizedDescription)")
    }
}

Reading Data from Disk

Reading data back from the disk is just as straightforward.

You locate the exact same file URL and use the String(contentsOf:) or Data(contentsOf:) initializers.

Loading a String:

func loadMessage() -> String {
    let url = getDocumentsDirectory().appendingPathComponent("message.txt")
    do {
        let savedMessage = try String(contentsOf: url, encoding: .utf8)
        return savedMessage
    } catch {
        print("Failed to load or file doesn't exist.")
        return "Default Welcome Message"
    }
}

Persisting Complex Objects

To save complex arrays or custom structs, you must first convert them into Data.

You can do this by making your struct conform to Codable and using a JSONEncoder.

Once the object is encoded into JSON Data, you simply write that Data to the Documents directory just like the string example!


Exercise

Which class in Swift is used to interact with the file system, locate directories, and manage files?