Sobes.tech
Junior

How to save and read data structures using User Defaults?

sobes.tech AI

Answer from AI

User Defaults only stores a limited set of types: Data, String, Number, Date, Array, Dictionary. To store custom data structures, they need to be encoded into Data and decoded back.

The Codable protocol (a combination of Encodable and Decodable) is used.

  1. Defining the structure: The structure must conform to the Codable protocol.

    struct MyData: Codable {
        let id: Int
        let name: String
        let isActive: Bool
    }
    
  2. Saving: Encode the structure into Data using JSONEncoder and save it in User Defaults.

    let myStruct = MyData(id: 1, name: "Example", isActive: true)
    
    // Encode to Data
    let encoder = JSONEncoder()
    if let encodedData = try? encoder.encode(myStruct) {
        // Save Data with key
        UserDefaults.standard.set(encodedData, forKey: "myCustomData")
    } else {
        // Handle encoding error
        print("Failed to encode struct")
    }
    
  3. Reading: Retrieve Data from User Defaults and decode it back into the structure using JSONDecoder.

    // Retrieve Data by key
    if let savedData = UserDefaults.standard.data(forKey: "myCustomData") {
        // Decode Data back into structure
        let decoder = JSONDecoder()
        if let loadedStruct = try? decoder.decode(MyData.self, from: savedData) {
            // Use the loaded structure
            print("Loaded struct: \(loadedStruct)")
        } else {
            // Handle decoding error
            print("Failed to decode data")
        }
    } else {
        // No data found for key
        print("No data found for key")
    }
    

Key points:

  • User Defaults is not intended for storing large amounts of data or confidential information.
  • Using Codable with JSONEncoder/JSONDecoder is the standard way to save custom types as Data.
  • Use try? and handle potential encoding/decoding errors.
  • For saving arrays of structures, Codable is also used.
// Example of saving an array of structures
let dataArray: [MyData] = [
    MyData(id: 1, name: "A", isActive: true),
    MyData(id: 2, name: "B", isActive: false)
]

let encoder = JSONEncoder()
if let encodedArrayData = try? encoder.encode(dataArray) {
    UserDefaults.standard.set(encodedArrayData, forKey: "myCustomArray")
}

// Example of reading an array of structures
if let savedArrayData = UserDefaults.standard.data(forKey: "myCustomArray") {
    let decoder = JSONDecoder()
    if let loadedArray = try? decoder.decode([MyData].self, from: savedArrayData) {
        print("Loaded array: \(loadedArray)")
    }
}