In this post, we will see how to save a list of objects into UserDefaults.
First of all, we create a new Swift project and we add a Struct called Person:
[PERSON.SWIFT]
import Foundation
// Identifiable is a protocol and means that our object can be
// identified uniquely.
// Codable is a protocol and indicate whether an object can be
// encoded into JSON data, or materialized from JSON data.
struct Person: Identifiable, Codable {
let id = UUID()
var Name: String
var Surname: String
var Age: Int
}
Then, we define a Class called People, used to save and load data from UserDefaults:
[PEOPLE.SWIFT]
import Foundation
class People: ObservableObject {
@Published var lstPeople = [Person](){
didSet{
// every time value of lstPeople change, system will save new value
// into UserDefaults
let encoder = JSONEncoder()
if let encoded = try? encoder.encode(lstPeople){
UserDefaults.standard.set(encoded, forKey: "People")
}
}
}
init() {
// everytime we create an instance of People, system will load the value
// from UserDefaults
if let savedPeople = UserDefaults.standard.data(forKey: "People"){
if let decodedPeople = try? JSONDecoder().decode([Person].self, from: savedPeople){
lstPeople = decodedPeople
return
}
}
lstPeople = []
}
}
Now, we create a SwiftUI View file called AddPerson where we will define the form for adding a new person:
[ADDPERSON.SWIFT]
import SwiftUI
struct AddPerson: View {
@ObservedObject var people: People
// var used to dismiss the sheet
@Environment(\.dismiss) var dismiss
@State private var name = ""
@State private var surname = ""
@State private var age = 0
var body: some View {
NavigationView{
Form{
TextField("Name", text: $name)
TextField("Surname", text: $surname)
TextField("Age", value: $age, format: .number)
.keyboardType(.numberPad)
}
.navigationTitle("Add new Person")
.toolbar{
Button("Save"){
let newPerson = Person(Name: name, Surname: surname, Age: age)
people.lstPeople.append(newPerson)
dismiss()
}
}
}
}
}
struct AddPerson_Previews: PreviewProvider {
static var previews: some View {
AddPerson(people: People())
}
}
Finally, we define the ContentView file:
[CONTENTVIEW.SWIFT]
struct ContentView: View {
@StateObject var people = People()
@State private var showAddnewPerson = false
var body: some View {
NavigationView{
List{
ForEach(people.lstPeople){item in
HStack{
VStack(alignment: .leading){
Text(item.Surname)
.font(.headline)
Text(item.Name)
}
Spacer()
Text(item.Age, format: .number)
}
}
.onDelete(perform: RemovePerson)
}
.navigationTitle("List People")
.toolbar{
Button{
showAddnewPerson = true
}label: {
Image(systemName: "plus")
}
}
.sheet(isPresented: $showAddnewPerson){
AddPerson(people: people)
}
}
}
func RemovePerson(at offsets: IndexSet){
people.lstPeople.remove(atOffsets: offsets)
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
We have done and now, if we run the application, this will be the result: