Here’s an improved version of your written text:
While browsing Reddit recently, I came across a question that prompted me to start this blog. I wanted to share my expertise with others so that we can all become better developers.
As I was reviewing some code, I noticed that sensitive data such as login information should not be saved to UserDefaults. Instead, it should be stored in Keychain. However, we can use AppStorage for other types of data.
To demonstrate this, I’ve created a SampleStorage
class that uses AppStorage
to store and retrieve data. This class includes methods for saving and retrieving employee information in a dictionary
format. Since the data is stored in a dictionary
in dictionary
format, we need to encode
and decode
it before saving to UserDefaults
(line 9 and 14).
final class SampleStorage: ObservableObject {
@AppStorage("name")
var name: String = ""
@AppStorage("employeeInformation")
var employeeData: Data = Data()
func saveEmployeeInformation(info: [[String: String]]) {
guard let newData = try? JSONEncoder().encode(info) else { return }
employeeData = newData
}
func employeeInformation() -> [[String: String]]? {
guard let employeeInformation = try? JSONDecoder().decode([[String: String]].self, from: employeeData)
else {
return nil
}
return employeeInformation
// Advanced: - One liner return approach -
// return try? JSONDecoder().decode([[String: String]].self, from: employeeData)
}
}
Here’s a sample view that demonstrates how to use the SampleStorage
class to store and retrieve employee information.
import SwiftUI
struct UserDefaultSampleView: View {
@ObservedObject
private var storage = SampleStorage()
var body: some View {
VStack {
Text("Name: " + storage.name)
.padding()
Text("Employee information: ")
Text(storage.employeeInformation()?.description ?? "")
Divider()
updateNameButton
updateEmployeeInformationButton
removeEmployeeInformation
}
}
// MARK: - Private -
@ViewBuilder
private var updateNameButton : some View {
Button("Update name") {
guard let name = randomName() else { return }
storage.name = name
}
.padding()
}
@ViewBuilder
private var updateEmployeeInformationButton: some View {
Button("Update employee information") {
guard let name = randomName(),
let middleName = randomName(),
let lastName = randomName()
else {
return
}
let information = [
["name": name],
["middleName": middleName],
["lastName": lastName]
]
storage.saveEmployeeInformation(info: information)
}
.padding()
}
@ViewBuilder
private var removeEmployeeInformation: some View {
Button("Remove employee information") {
storage.employeeData = Data()
}
.padding()
}
private func randomName() -> String? {
let names = ["Zoey", "Chloe", "Amani", "Amaia", "Tom", "John"]
guard let randomName = names.randomElement() else { return nil }
return randomName
}
}
Feel free to post any suggestions, questions in the comments below.