Having trouble with "Return from initializer without initializing all stored properties" error

606 Views Asked by At

Having trouble resolving this error "Return from initializer without initializing all stored properties"

Here is the code that prompted the error,

import SwiftUI

struct TaskEditView: View
{
    @Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
    @Environment(\.managedObjectContext) private var viewContext
    @EnvironmentObject var dateHolder: DateHolder
    @ObservedObject var notificationManager: NotificationManager
    
    @State var selectedTaskItem: TaskItem?
    @State var name: String
    @State var desc: String
    @State var dueDate: Date
    @State var scheduleTime: Bool
    
    init(passedTaskItem: TaskItem?, initialDate: Date)
    {
        if let taskItem = passedTaskItem
        {
            _selectedTaskItem = State(initialValue: taskItem)
            _name = State(initialValue: taskItem.name ?? "")
            _desc = State(initialValue: taskItem.desc ?? "")
            _dueDate = State(initialValue: taskItem.dueDate ?? initialDate)
            _scheduleTime = State(initialValue: taskItem.scheduleTime)
        }
        else
        {
            
            _name = State(initialValue: "")
            _desc = State(initialValue: "")
            _dueDate = State(initialValue: initialDate)
            _scheduleTime = State(initialValue: false)
        }
    } //error appears right here 
    
    var body: some View
    {
        NavigationView{
            
        Form
        {
            Section(header: Text("ToDo"))
            {
                TextField("Name", text: $name)
                TextField("Description", text: $desc)
            }
           
            Section(header: Text("Deadline"))
            {
                Toggle("Schedule Time", isOn: $scheduleTime)
                DatePicker("Date", selection: $dueDate, displayedComponents: displayedComps())
            }
            
            if selectedTaskItem?.isCompleted() ?? false
            {
                Section(header: Text("Completed"))
                {
                    Text(selectedTaskItem?.completedDate?.formatted(date: .abbreviated, time: .shortened) ?? "")
                }
            }
            
            Section()
            {
                Button("Save", action: saveAction)
                    .font(.headline)
                    .foregroundColor(.green)
                    .padding(.horizontal)
                
            }
            .navigationTitle("Create New ToDo ")
           
            }
        }
    }
    
    func displayedComps() -> DatePickerComponents
    {
        return scheduleTime ? [.hourAndMinute, .date] : [.date]
    }
    
    func saveAction()
    {
        withAnimation
        {
            if selectedTaskItem == nil
            {
                selectedTaskItem = TaskItem(context: viewContext)
            }
        
            selectedTaskItem?.created = Date()
            selectedTaskItem?.name = name
            selectedTaskItem?.desc = desc
            selectedTaskItem?.dueDate = dueDate
            selectedTaskItem?.scheduleTime = scheduleTime
            
            dateHolder.saveContext(viewContext)
            self.presentationMode.wrappedValue.dismiss()
            
        }
        
        let dateComponents = Calendar.current.dateComponents([.hour, .minute], from: dueDate)
        guard let hour = dateComponents.hour, let minute = dateComponents.minute else { return }
        notificationManager.createLocalNotification(title: name, hour: hour, min: minute) { error in
                if error == nil {}
        }
        
    }
}


struct TaskEditView_Previews: PreviewProvider {
    static var previews: some View {
        TaskEditView(passedTaskItem: TaskItem(), initialDate: Date())
    }
}

I looked online and it said that I have to initialize all my proporties but im unsure how to do that for the

_selectedTaskItem

in the else statement.

Im very new to coding and much help would be appreciated Thanks

1

There are 1 best solutions below

1
On

Yes, you still need to initialize selectedTaskItem, even if its initial value is nil.

The good news is that passedTaskItem works in both cases, so you can move that initialization out of the if clause:

init(passedTaskItem: TaskItem?, initialDate: Date) {
  _selectedTaskItem = State(initialValue: passedTaskItem)

  if let taskItem = passedTaskItem {
    _name = State(initialValue: taskItem.name ?? "")
    // etc.