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]
1 2 3 4 5 6 7 8 9 10 11 12 | 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]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | 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]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | 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]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | 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:







