Search code examples
swiftuitableviewcore-datansfetchedresultscontrollerdelete-row

CoreData - Deleting row from tableView


I need some help with this code:

func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
        println("section and row \(indexPath.section) \(indexPath.row) ")
        if self.fetchedResultsController == nil {
            println("error when trying to delete object from managed object")

        } else if (editingStyle == UITableViewCellEditingStyle.Delete) {
            moc?.deleteObject(detailsArray[indexPath.row] as NSManagedObject)
            detailsArray.removeAtIndex(indexPath.row)

            var error: NSError?
            moc?.save(&error)
        }
    }
// MARK: NSFetchedResultsControllerDelegate
    func controllerWillChangeContent(controller: NSFetchedResultsController) {
        self.exerciseTableView.beginUpdates()
    }
    func controller(controller: NSFetchedResultsController,
        didChangeObject anObject: AnyObject,
        atIndexPath indexPath: NSIndexPath?,
        forChangeType type: NSFetchedResultsChangeType,
        newIndexPath: NSIndexPath?)
    {
        switch type {
        case NSFetchedResultsChangeType.Insert:
            // Note that for Insert, we insert a row at the __newIndexPath__
            if let insertIndexPath = newIndexPath {
                self.exerciseTableView.insertRowsAtIndexPaths([insertIndexPath], withRowAnimation: UITableViewRowAnimation.Fade)
            }
        case NSFetchedResultsChangeType.Delete:
            // Note that for Delete, we delete the row at __indexPath__
            if let deleteIndexPath = indexPath {
                self.exerciseTableView.deleteRowsAtIndexPaths([deleteIndexPath], withRowAnimation: UITableViewRowAnimation.Fade)
            }
        case NSFetchedResultsChangeType.Update:
            // Note that for Update, we update the row at __indexPath__
            if let updateIndexPath = indexPath {
                let cell = self.exerciseTableView.cellForRowAtIndexPath(updateIndexPath)
                let details = self.fetchedResultsController!.objectAtIndexPath(updateIndexPath) as? TrainingDetails

                cell!.textLabel!.text = "\(details!.exerciseName)"
                cell!.detailTextLabel!.text = "Sets: #\(details!.setsNumber) Reps: #\(details!.repsNumber)"
            }
        case NSFetchedResultsChangeType.Move:
            // Note that for Move, we delete the row at __indexPath__
            if let deleteIndexPath = indexPath {
                self.exerciseTableView.deleteRowsAtIndexPaths([deleteIndexPath], withRowAnimation: UITableViewRowAnimation.Fade)
            }

            // Note that for Move, we insert a row at the __newIndexPath__
            if let insertIndexPath = newIndexPath {
                self.exerciseTableView.insertRowsAtIndexPaths([insertIndexPath], withRowAnimation: UITableViewRowAnimation.Fade)
            }
        }    }

    func controller(controller: NSFetchedResultsController,
        didChangeSection sectionInfo: NSFetchedResultsSectionInfo,
        atIndex sectionIndex: Int,
        forChangeType type: NSFetchedResultsChangeType)
    {
        switch type {
        case .Insert:
            let sectionIndexSet = NSIndexSet(index: sectionIndex)
            self.exerciseTableView.insertSections(sectionIndexSet, withRowAnimation: UITableViewRowAnimation.Fade)
        case .Delete:
            let sectionIndexSet = NSIndexSet(index: sectionIndex)
            self.exerciseTableView.deleteSections(sectionIndexSet, withRowAnimation: UITableViewRowAnimation.Fade)
        default:
            ""
        }
    }
    func controllerDidChangeContent(controller: NSFetchedResultsController) {
        exerciseTableView.endUpdates()
    }
}

So, the problem is whenever I try to delete something from the table view, it only runs properly if it's the first item in the table view. If I try to delete any other item that's not the first one, the app crashed and it says Array index out of range.

I don't get where's my mistake. Can someone help me?

I hope we can crack this! Thanks in advance.

UPDATE

cellForRowAtIndexPath function:

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

        let cell = tableView.dequeueReusableCellWithIdentifier("exerciseCell", forIndexPath: indexPath) as! UITableViewCell
        let details = fetchedResultsController!.objectAtIndexPath(indexPath) as! TrainingDetails
        cell.textLabel!.text = "\(details.exerciseName)"
        cell.detailTextLabel!.text = "Sets: #\(details.setsNumber) Reps: #\(details.repsNumber)"

        return cell
    }

Solution

  •   func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) { 
    
            println("section and row \(indexPath.section) \(indexPath.row) ") 
            if self.fetchedResultsController == nil { 
                 println("error when trying to delete object from managed object") 
    
            } else if (editingStyle == UITableViewCellEditingStyle.Delete) { 
    
             switch editingStyle { 
    
                   case .Delete: 
                         moc?.deleteObject(fetchedResultsController?.objectAtIndexPath(indexPath) as! TrainingDetails) 
                         moc?.save(nil) 
    
                  case .Insert: 
                            break 
                  case .None: 
                            break 
                 } 
            } 
         }
    

    This might be helpful.