Search code examples
swiftuitableviewcore-datauitableviewrowaction

how I can load a data from database with row actions in swift


I'm building reminder app, when I swap to the left I can delete and update the reminder; when I press on edit button as shown below, it suppose to load data from data base, so I can edit and update the data, but instead it just works like create a new reminder.

and how I can resize the row actions.

ReminderTable.swift

  override func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [UITableViewRowAction]? {

        let deleteAction = UITableViewRowAction(style: UITableViewRowActionStyle.Default, title: "Delete",handler: { (action, indexPath) -> Void in


            if let managedObjectContext = (UIApplication.sharedApplication().delegate as? AppDelegate)?.managedObjectContext {

                let reminderToDelete = self.fetchResultController.objectAtIndexPath(indexPath) as! ReminderData
                managedObjectContext.deleteObject(reminderToDelete)

                do {
                    try managedObjectContext.save()
                } catch {
                    print(error)
                }
            }
        })


        let editAction = UITableViewRowAction(style: UITableViewRowActionStyle.Default, title: "Edit",handler: { (action, indexPath) -> Void in

                let st:UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
                let vc :UINavigationController = st.instantiateViewControllerWithIdentifier("Reminder") as! UINavigationController
                self.presentViewController(vc, animated: true, completion: nil)

        })


        deleteAction.backgroundColor = UIColor.redColor()
        editAction.backgroundColor = UIColor.blueColor()
        return [deleteAction,editAction]
    }

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        if segue.identifier == "Reminder" {

            let task = segue.destinationViewController as! Reminder


            let indexpath = self.tableView.indexPathForSelectedRow

            let row = indexpath?.row

            task.reminders = reminders[row!]

        }
    }

Reminder.swift

    override func viewDidLoad() {
        super.viewDidLoad()

    dateTextField.delegate = self
    nameTextField.delegate = self



    if let reminderContent = reminders

    {

        nameTextField.text = reminderContent.name
      dateTextField.text = reminderContent.stringForDate()
        timePick.date = reminderContent.time!
      }  

        let dateFormatter = NSDateFormatter()
        dateFormatter.dateFormat = "MM-dd-yyyy"
        dateFormatter.stringFromDate(reminderContent.date!)

        let timeFormatter = NSDateFormatter()
        timeFormatter.dateFormat = "hh:mma"
            timeFormatter.stringFromDate(reminderContent.time!)

    }

 func inserte(){

        let storingName = nameTextField.text

        let dateFormatter = NSDateFormatter()
        dateFormatter.dateFormat = "MM-dd-yyyy"
        let date = dateFormatter.dateFromString(dateTextField.text!)

        if reminders == nil {

            if let managedObjectContext = (UIApplication.sharedApplication().delegate as? AppDelegate)?.managedObjectContext {
                reminders = NSEntityDescription.insertNewObjectForEntityForName("Reminder", inManagedObjectContext: managedObjectContext) as? ReminderData

                reminders!.name = storingName!
                reminders.date = date
                reminders.time = timePick.date



                do {
                    try managedObjectContext.save()
                } catch {
                    print(error)
                    return
                }
            }


        }
    }

note that I'm still kinda newbie in iOS development

thanks in advance

enter image description here


Solution

  • You have not shown us an important piece of the code, what are you doing in Reminder View Controller?

    From what I can see you are setting a reminders property on the Reminder VC to the selected row, is this code running as expected?

    Once in the Reminder View Controller, I'm guessing you have a form, are you setting the properties in viewDidLoad/viewDidAppear?

    I would expect to see something like:

    func viewDidLoad(animated:Bool) {
        Super.viewDidLoad(animated:animated)
    
        DescriptionTextField.text = reminder.description
        LocationTextField.text = reminder.location
        // ... And so on, filling out each property on your model
    }
    

    This functionality isn't built in, so you need to build the form and handle the validation of the data and saving into the managed object context (make sure you do this on the same thread)

    After looking over the code on github I've updated it and managed to get the reminder to update the changes and show this on the table view.

    The main change needed was:

    // near the top of the file..
    var reminder:ReminderData?
    
    // then further down
    func update(){
    
        let storingName = nameTextField.text
        let dateFormatter = NSDateFormatter()
        dateFormatter.dateFormat = "MM-dd-yyyy"
        let date = dateFormatter.dateFromString(dateTextField.text!)
    
    
        let managedObjectContext = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext
    
    
        if let reminder = reminder {
            reminder.name = storingName
            if let categoryStorage = storingCategory {
                reminder.category = categoryStorage
            }
    
            reminder.date = date
            reminder.time = timePick.date
    
            do {
                try managedObjectContext.save()
    
            } catch let error as NSError {
                print("ERROR in update: \(error)")
            }
        }
    
        self.navigationController?.popViewControllerAnimated(true)
    
    }
    

    The main change here is not trying to fetch the reminder again, you have passed the managedObject(Reminder) over to the editVC so dont need to fetch it again. so you just update the values and then save.

    Also when you was fetching you was fetching all records. If you want to do it this way you would likely pass over the reminder ID to the Reminder VC and then load it by ID, modify and save. in order to do this you'd need to add an ID field and update your fetch to include a predicate, but for now you dont need it.