Reputation: 1954
I am updating certain parts of coredata and I want the NSFetchedResultsController to automatically reload the tableview with all the animations. I am changing a coredata element that is used to sort tableview. I am doing this by swiping to the right on the cell and then changing that particular tableviewcell's priorityNumber to zero so that the task goes to the bottom and few other things. I want the table to reload but with the animations. right now I am just doing tableView.reload() and it's just not working right.
I want to see the animation of the cell going to the bottom of the device. Any help will be appreciated!
Here is the code: Changes I am bringing to the coreData:
func tableView(_ tableView: UITableView,
leadingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration?
{
let closeAction = UIContextualAction(style: .normal, title: "✓", handler: { (ac:UIContextualAction, view:UIView, success:(Bool) -> Void) in
//???
self.fetchedResultsController.object(at: indexPath).sTaskCompleted = !(self.fetchedResultsController.object(at: indexPath).sTaskCompleted)
if ( self.fetchedResultsController.object(at: indexPath).sTaskCompleted)
{
print("Completed")
//Change priority number to 0 after saving their current priority number in previousPN
//Change priority circle color
//Change background of the cell to something else
self.fetchedResultsController.object(at: indexPath).sPreviousPN = self.fetchedResultsController.object(at: indexPath).sPriorityNumber
self.fetchedResultsController.object(at: indexPath).sPriorityNumber = 0
self.fetchedResultsController.object(at: indexPath).cellbackgroundColor = UIColor(red:0.93, green:0.91, blue:0.91, alpha:1.0)
self.fetchedResultsController.object(at: indexPath).previousPriorityColor = self.fetchedResultsController.object(at: indexPath).sPriorityColor
self.fetchedResultsController.object(at: indexPath).sPriorityColor = .clear
var error: NSError?
do {
// Save The object
try self.moContext.save()
print("SAVED")
} catch let error1 as NSError {
error = error1
}
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3, execute: {
UIView.transition(with: tableView,
duration: 0.15,
options: .transitionCrossDissolve,
animations: { self.tableView.reloadData() })
})
} else {
print("InCompleted")
self.fetchedResultsController.object(at: indexPath).sPriorityNumber = self.fetchedResultsController.object(at: indexPath).sPreviousPN
self.fetchedResultsController.object(at: indexPath).cellbackgroundColor = .white
self.fetchedResultsController.object(at: indexPath).sPriorityColor = self.fetchedResultsController.object(at: indexPath).previousPriorityColor
var error: NSError?
do {
// Save The object
try self.moContext.save()
print("SAVED")
} catch let error1 as NSError {
error = error1
}
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3, execute: {
UIView.transition(with: tableView,
duration: 0.15,
options: .transitionCrossDissolve,
animations: { self.tableView.reloadData() })
})
}
success(true)
})
closeAction.backgroundColor = UIColor(red:0.18, green:0.87, blue:0.65, alpha:1.0)
return UISwipeActionsConfiguration(actions: [closeAction])
}
Now how to use FRC delegate method (.update) to refresh the tableView with appropriate animations.
Upvotes: 2
Views: 1503
Reputation: 561
The table view controller needs to conform to NSFetchedResultsControllerDelegate and implement its delegate methods. If configured correctly, the fetched results controller will watch the managed object context for changes and call the appropriate delegate method to update the table view with animations.
class TaskTableViewController: UITableViewController, NSFetchedResultsControllerDelegate {
var fetchedResultsController: NSFetchedResultsController<Task>!
override func viewDidLoad() {
super.viewDidLoad()
configureFetchedResultsController()
}
func configureFetchedResultsController() {
if fetchedResultsController == nil {
// 1. Get fetch request
let fetchRequest: NSFetchRequest<Task> = Task.fetchRequest()
// 2. Add sort descriptors
fetchRequest.sortDescriptors = [NSSortDescriptor(key: "sPriorityNumber", ascending: false)]
// 3. Configure the FRC
fetchedResultsController = NSFetchedResultsController<Task>(fetchRequest: fetchRequest, managedObjectContext: CoreDataStack.context, sectionNameKeyPath: nil, cacheName: nil)
// 4. Set the FRC delegate as self
fetchedResultsController.delegate = self
}
// 5. Tell the FRC to start watching the MOC for changes
do {
try fetchedResultsController.performFetch()
} catch {
NSLog("Error starting fetched results controller \(error)")
}
}
// FRC delegate methods
func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>,
didChange anObject: Any,
at indexPath: IndexPath?,
for type: NSFetchedResultsChangeType,
newIndexPath: IndexPath?) {
switch type {
case .insert:
guard let newIndexPath = newIndexPath else { return }
tableView.insertRows(at: [newIndexPath], with: .automatic)
case .delete:
guard let indexPath = indexPath else { return }
tableView.deleteRows(at: [indexPath], with: .fade)
case .move:
tableView.reloadData()
case .update:
guard let indexPath = indexPath else { return }
tableView.reloadRows(at: [indexPath], with: .automatic)
}
}
func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>,
didChange sectionInfo: NSFetchedResultsSectionInfo,
atSectionIndex sectionIndex: Int,
for type: NSFetchedResultsChangeType) {
switch type {
case .delete:
tableView.deleteSections(IndexSet(integer: sectionIndex), with: .automatic)
case .insert:
tableView.insertSections(IndexSet(integer: sectionIndex), with: .automatic)
default:
break
}
}
}
Upvotes: 1