I am using an NSFetchedResultsController. I can't find any straightforward tutorials that walk through it for Swift 3
.
So here is what I have done so far. I have successfully populated my table using an NSFetchedResultsController
that fetches the inserted data from core data. I created an attribute in my core data model called, orderPosition
that is declared as Int32
. I haven't done anything with this attribute in regards to adding and saving data to core data upon insert.
In my fetch func
where I initialize the NSFetchedResultsController
, I have modified my sort descriptor to include the following code:
let sortDescriptor = NSSortDescriptor(key: "orderPosition", ascending: true)
fetchRequest.sortDescriptors = [sortDescriptor]
Then I implemented the tableView
func:
func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
attemptFetch()
var objects = self.controller.fetchedObjects!
self.controller.delegate = nil
let object = objects[sourceIndexPath.row]
objects.remove(at: sourceIndexPath.row)
objects.insert(object, at: destinationIndexPath.row)
var i = 0
for object in objects {
object.setValue(i += 1, forKey: "orderPosition")
}
appdel.saveContext()
self.controller.delegate = self
}
In my implementation of the didChange
anObject func, I included the switch-case for .insert
, .delete
, .update
, and .move
.
My .move
case looks like the following:
case.move:
if let indexPath = indexPath {
tableView.deleteRows(at: [indexPath], with: .fade)
}
if let indexPath = newIndexPath {
tableView.insertRows(at: [indexPath], with: .fade)
}
break
Please help me figure this out. I have been spending weeks trying to understand this. I have gone through many if not all stack overflow questions on this. I implemented some of the loop ideas from one because I had a similar thought process to approach this but it didn't work. There are no Swift 3 core data tutorials/videos that I have come across that will really help me solve and understand this well. I don't want to give up on this.
Just implemented similar functionality in my project.Turned out to be easier than it seemed.
Here is an update for your moveRowAt
method
func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
// NOT NEEDED, SINCE I ASSUME THAT YOU ALREADY FETCHED ON INITIAL LOAD
// attemptFetch()
var objects = self.controller.fetchedObjects!
// NOT NEEDED
//self.controller.delegate = nil
let object = objects[sourceIndexPath.row]
objects.remove(at: sourceIndexPath.row)
objects.insert(object, at: destinationIndexPath.row)
// REWRITEN BELOW
//var i = 0
//for object in objects {
// object.setValue(i += 1, forKey: "orderPosition")
//}
for (index, item) in items.enumerated() {
item.orderPosition = index
}
appdel.saveContext()
//self.controller.delegate = self
}
In didChange
technically you don't need any code. The table is updated in place, when you move the item in it. And your data in coreData is updated when you save the context. So next time the data is fetched, based on the sortDescriptor you have, it will come in sorted by orderPosition.
Worked for me. Let me know, if you have any questions.
Swift deviates from C in that the =, += and other assignment-like operations returns Void
. So your line object.setValue(i += 1, forKey: "orderPosition")
is setting i
to be one more but is always setting the position to be 0. Try instead:
var i = 0
for object in objects {
i += 1
object.setValue(i, forKey: "orderPosition")
}
or if you want to simplify your code a bit you can do
for (i, object) in objects.enumerated() {
object.setValue(i, forKey: "orderPosition")
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With