2

I am trying to get the moveRowAtIndexPath method to work using Core Data. My program is user-driven meaning that the user updates the data repeatedly and is basically a table view that displays the name of an Entity. Each Entity has two attributes: a name and an integer that represents its position in the tableView, let's call it orderPosition. I have also created a local variable that stores the lastIndex, which is the number of objects in my array. This allows me to assign an index value to each Entity that I create (last place in table). What I can't manage to figure out is how to use the stored attribute orderPosition in my entity to create a sorted array for the tableView in my View Controller and how to use this to make moveRowAtIndexPath work.

override func viewWillAppear(animated: Bool) {
    let appDelegate: AppDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
    let context = appDelegate.managedObjectContext!

    let fetchReq = NSFetchRequest(entityName: "Object")

    objectData = context.executeFetchRequest(fetchReq, error: nil)!

    lastIndex = objectData.count

    tableView.reloadData()
}

override func tableView(tableView: UITableView, moveRowAtIndexPath sourceIndexPath: NSIndexPath, toIndexPath destinationIndexPath: NSIndexPath) {

    let val: AnyObject = self.objectsData.removeAtIndex(sourceIndexPath.row)

    self.objectsData.insert(val, atIndex: destinationIndexPath.row)

    let appDelegate: AppDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
    let context = appDelegate.managedObjectContext!

    var fetchReq = NSFetchRequest(entityName: "Object")
    fetchReq.predicate = NSPredicate(format: "orderPosition = %@", sourceIndexPath.row)

    if let fetchResults = appDelegate.managedObjectContext!.executeFetchRequest(fetchReq, error: nil) as? [NSManagedObject] {
        if fetchResults.count != 0{

            var managedObject = fetchResults[0]
            managedObject.setValue(destinationIndexPath.row, forKey: "orderPosition")

            context.save(nil)
        }
    }
}

2 Answers 2

1

You can create a NSSortDescriptor to fetch the data:

let sortDescriptor = NSSortDescriptor(key: "orderPosition", ascending: true)
let sortDescriptors = [sortDescriptor]
fetchReq.sortDescriptors = sortDescriptors
Sign up to request clarification or add additional context in comments.

6 Comments

Okay, but now how can I make the change in the store in moveRowAtIndexPath? I edited the implementation in the question to what I'm trying to do but isn't working..
@rodrigochousal Sorry I think I may understand you wrong, are you having problems saving or reading from core data?
Both, I initially needed to sort my array, but now I don't know how to make the change of moving the cells around in Core Data. Sorry, I am fairly new to Core Data..
@rodrigochousal You don't need to sort the array, if you use the NSSortDescriptor I place on top the result will come sorted to you, you just need to keep it update after
I know, but the NSSortDescriptor just sorts the local array. The problem is that while my array is sorted, the orderPosition attribute is not being updated in the store, so every time that the table view is loaded, the changes done in moveRowAtIndexPath are reset.
|
0

First, your array with a fetch requests necessary to retrieve the objects is not very efficient. Just use a NSFetchedResultsController and the index paths will automatically point to your objects. In addition, you get great memory and performance optimizations for free.

As has been pointed out in the comments, you need to save any new order. E.g. in viewWillDisappear or just after re-ordering. Depending on your setup, it could be something similar to this:

for var i = 0; i < self.fetchedResultsController.fetchedObjects.count; i++ {
   let indexPath = NSIndexPath(row:i section:0)
   var object = self.fetchedResultsController.objectAtIndexPath(indexPath)
   object.orderPosition = i+1
}
self.managedObjectContext.save(nil)

Make sure you add the sort descriptor to you fetched results controller. If you decide to dispense with the fetched results controller (not recommended) you have to include the sorting in the fetch request for populating your data array in viewDidLoad.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.