How can use UserDefaults to store custom class ?
Tags: swift, userdefaults, ios, datapersistence
Published: 2021-10-04 06:50:54

Last time, we reviewed how could use UserDefault to save user's data with common data types into local device.
Please refer to [Local Data Persistence - UserDefaults (Basic)](https://dev.to/danieljang/local-data-persistence-basic-userdefaults-31kd)

Typically UserDefault class doesn't support saving user's data with custom class!
###_But if we convert user's custom class to NSData then UserDefaults class can store the converted user's custom class by NSData to local device._

##Lets' coding and test...

> ####1) Declare custom class with "Codable" protocol
  * We will convert the custom class by using JSONEncoder() and JSONEncoder will return "Data" type which can be stored through UserDefaults. At this time we should declare custom class with "Codable" keyword. _"Codable" means that the custom class will be converted by JSONEncoder() for data saving and JSONDecoder() for data loading._
```swift
class Product: Codable {
    let name: String
    let modelNum: String
    
    init(name: String, modelNum: String){
        self.name = name
        self.modelNum = modelNum
    }
}
```

> ####2) [Save data to local device] Encoding custom class by JSONEncoder() to convert custom class as "Data" type and the converted "Data" type will be stored into local device through UserDefaults.set(Any?, forKey:) method.
```swift
let encoder = JSONEncoder()
let appleWatch = Product(name: "Apple Watch 7", modelNum: "W20215313")
do {
    let encodedData = try encoder.encode(appleWatch)
    defaults.set(encodedData, forKey: "AppleWatch")
}catch{
    print("Error encoding process\(error)")
}
```

As we could study last article, you could find ".plist" file from your device to see stored data as below image.
Please refer to this link [Local Data Persistence - UserDefaults (Basic)](https://dev.to/danieljang/local-data-persistence-basic-userdefaults-31kd)
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v4zx6s4h77sefy3120p2.png)


> ####3) [Load data from local device] We load converted custom class as "Data" type what we saved at 2) from local device.
  * defaults.object(forKey: ) method will grab(return) stored data from local device 
  * The stored(returned) data should be "Data" type because we converted custom class to "Data" type and we stored the "Data" into local device at 2)
  * Then we should decode returned data from "Data" type to custom class again by using JSONDecoder() to use it in our code as below code.

```swift
if let data = defaults.object(forKey: "AppleWatch")as? Data {
    let decoder = JSONDecoder()
    do {
        let decodedData = try decoder.decode(Product.self, from: data)
        print(decodedData.name)
        print(decodedData.modelNum)
    }catch{
        print("Error decoding\(error)")
    }
}
```

> Result:
Apple Watch 7
W20215313


Finally we could see how we store common data type as integer, string, float, array, dictionary and even custom class.

Warning! UserDefaults class is not good solution to save secure data as password or banking account but UserDefault is perfect solution to save small data without secure information as user's setting. 🤗

Thank you for your reading.
Daniel JANG