Home > Blockchain >  Saving Int to Core Data SWIFTUI
Saving Int to Core Data SWIFTUI

Time:04-28

Below is a view within my Task management app, and I am trying to make my picker display a certain color when it is chosen. My question is how do I save the Ints used for the priority and color picker within Core data? I can't figure out how to convert the int value into int32, and it can't start as an Int32 object because then it wouldn't be able to be used as the selector for the background color of each picker. PLEASE HELP!

struct NewTask: View {
    @Environment(\.dismiss) var dismiss
    
    // MARK: Task Values
    @State var taskTitle: String = ""
    @State var taskDescription: String = ""
    @State var taskDate: Date = Date()
    
    var colors = ["Teal","Yellow","Pink"]
    @State var selectedColor: Int = 0
    
    var colorsColors = ["logoTeal","logoYellow","logoPink"]
    
    var selectedColorInt: String {
        get {
            return ("\(selectedColor)")
        }
    }
    
    var priorities = ["Urgent","Slightly Urgent","Not Urgent"]
    @State var selectedPriority: Int = 0
    
    
    var priorityColors = ["priorityRed","priorityYellow","priorityGreen"]

    
    // MARK: Core Data Context
    @Environment(\.managedObjectContext) var context
    
    @EnvironmentObject var taskModel: TaskViewModel
    var body: some View {
        
        NavigationView{
            List{
                Section {
                    TextField("Go to work", text: $taskTitle)
                    Picker("Priority", selection: $selectedPriority) {
                        ForEach(0..<priorities.count){
                            Text(priorities[$0])
                        }
                        .padding(5)
                        .foregroundColor(.white)
                        .background(priorityColors[selectedPriority])
                        .cornerRadius(5)
                        
                    }
                    Picker("Theme", selection: $selectedColor) {
                        ForEach(0..<colors.count){
                            Text(colors[$0])
                        }
                        .padding(5)
                        .foregroundColor(.black)
                        .background(colorColors[selectedColor])
                        .cornerRadius(5)
                    }
                } header: {
                    Text("Task Information")
                }

                Section {
                    TextEditor(text: $taskDescription)
                } header: {
                    Text("Task Description")
                }
                
                // Disabling Date for Edit Mode
                if taskModel.editTask == nil{
                    
                    Section {
                        DatePicker("", selection: $taskDate)
                            .datePickerStyle(.graphical)
                            .labelsHidden()
                    } header: {
                        Text("Task Date")
                    }
                }
            }
            .listStyle(.insetGrouped)
            .navigationTitle("Add New Task")
            .navigationBarTitleDisplayMode(.inline)
            // MARK: Disbaling Dismiss on Swipe
            .interactiveDismissDisabled()
            // MARK: Action Buttons
            .toolbar {
                
                ToolbarItem(placement: .navigationBarTrailing) {
                    Button("Save"){
                        
                        if let task = taskModel.editTask{
                            
                            task.taskTitle = taskTitle
                            task.taskDescription = taskDescription
                        }
                        else{
                            let task = Task(context: context)
                            task.taskTitle = taskTitle
                            task.taskDescription = taskDescription
                            task.taskDate = taskDate
                            /*task.selectedColor = selectedColor*/
                            /*task.selectedPriority = selectedPriority*/
                        }
                        
                        // Saving
                        try? context.save()
                        // Dismissing View
                        dismiss()
                    }
                    .disabled(taskTitle == "" || taskDescription == "")
                }
                
                ToolbarItem(placement: .navigationBarLeading) {
                    Button("Cancel"){
                        dismiss()
                    }
                }
            }
            // Loading Task data if from Edit
            .onAppear {
                if let task = taskModel.editTask{
                    taskTitle = task.taskTitle ?? ""
                    taskDescription = task.taskDescription ?? ""
                }
            }
        }
    }
    
}

CodePudding user response:

Here's the approach I would take.

First, as priority will only ever be one of three values, express it as an enum with an Int32 raw value, and with the text description and colours as properties of the enum:

enum Priority: Int32, CaseIterable {
    case urgent = 0
    case slightlyUrgent = 1
    case notUrgent = 2

    var description: String {
        switch self {
        case .urgent: return "Urgent"
        case .slightlyUrgent: return "Slightly Urgent"
        case .notUrgent: return "Not Urgent"
        }
    }

    var colorName: String {
        switch self {
        case .urgent: return "PriorityRed"
        case .slightlyUrgent: return "PriorityYellow"
        case .notUrgent: return "PriorityGreen"
        }
    }

    var color: Color { Color(colorName) }
}

In the form, this keeps your code a bit cleaner, and allows you to use semantic values over 0 when initialising your state variable:

@State private var selectedPriority: Priority = .urgent

Picker("Priority", selection: $selectedPriority) {
  ForEach(Priority.allCases, id: \.self) { priority in
    Text(priority.description)
      .padding(5)
      .foregroundColor(.black)
      .background(priority.color)
      .cornerRadius(5)
  }
}

Then, add an extension to your CoreData model that gives it a Priority property, adding a getter and setter so that it uses the stored column:

extension Task {
  var priorityEnum: Priority {
    get { Priority(rawValue: priority) ?? .urgent }
    set { priority = newValue.rawValue }
  }
}

Then when it comes to save the form details into the Core Data managed object, you can set task.priorityEnum to the picker's value, and the custom property will make sure that the correct Int32 value is stored.

Likewise, when loading the edit form's state variables from the task, referencing task.priorityEnum will get you a Priority value initialized with the integer that's stored in the database.

  • Related