Search code examples
swiftswiftuiuserdefaults

Saving a list using Codable or userDefaults


Can someone help me to save the list in this code using Codable or another methods. I am not able to use the UserDefaults in the code. Can anyone help me how to use save the lists so that when ever, I re-open my app, the list is still there. Thanks.

import SwiftUI
struct MainView: View {

    @State var br = Double()
    @State var loadpay = Double()
    @State var gp : Double = 0
    @State var count: Int = 1
    @State var listcheck = Bool()
    @StateObject var taskStore = TaskStore()
 @State var name = String()
    var userCasual = UserDefaults.standard.value(forKey: "userCasual") as? String ?? ""
    func addNewToDo() {
         taskStore.tasks.append(Task(id: String(taskStore.tasks.count + 1), toDoItem:  "load \(count)", amount: Double(gp)))
   }
    func stepcount() {
       
     count += 1
        
    }
    var body: some View {
        VStack {
            TextField("Name", text: $name)
            HStack {
            Button(action: { gp += loadpay }) {
                Text("Add Load")
            }
            Button(action: {
                addNewToDo()
            }) {
                Text("Check")
            }
        }
            Form {
                ForEach(self.taskStore.tasks) {
                    task in
                    Text(task.toDoItem)
                }
            }
        }
        Button(action: {
            UserDefaults.standard.set(name, forKey: "userCasual")})
        {Text("Save")}

}

}
struct Task : Identifiable {
    var id = String()
    var toDoItem = String()
    var amount : Double = 0
}

class TaskStore : ObservableObject {
    @Published var tasks = [Task]()
}

Solution

  • In Task adopt Codable

    struct Task : Codable, Identifiable {
        var id = ""
        var toDoItem = ""
        var amount = 0.0
    }
    

    In TaskStore add two methods to load and save the tasks and an init method

    class TaskStore : ObservableObject {
        @Published var tasks = [Task]()
        
        init() {
            load()
        }
        
        func load() {
            guard let data = UserDefaults.standard.data(forKey: "tasks"),
                  let savedTasks = try? JSONDecoder().decode([Task].self, from: data) else { tasks = []; return }
            tasks = savedTasks
        }
        
        func save() {
            do {
                let data = try JSONEncoder().encode(tasks)
                UserDefaults.standard.set(data, forKey: "tasks")
            } catch {
                print(error)
            }
        }
    }
    

    In the view call taskStore.save() to save the data.

    However: For large data sets UserDefaults is the wrong place. Save the data in the Documents folder or use Core Data.

    Side note: Never use value(forKey:) in UserDefaults, in your example there is string(forKey:)