Created
July 4, 2019 07:32
-
-
Save arashkashi/58c0450c7b9175c26a7c4515bd761103 to your computer and use it in GitHub Desktop.
fetch controller with data source for swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import UIKit | |
import CoreData | |
public protocol FetchedResultsDelegate { | |
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath, object: AnyObject) -> UITableViewCell | |
} | |
public class FetchedResultsDataSource: NSObject, UITableViewDataSource, NSFetchedResultsControllerDelegate { | |
public weak var tableView: UITableView? | |
public var frc: NSFetchedResultsController | |
public var delegate: FetchedResultsDelegate? | |
public init(fetchRequest: NSFetchRequest, context: NSManagedObjectContext = DataController.dataStack.mainContext, sectionNameKeyPath: String?) { | |
frc = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: context, sectionNameKeyPath: sectionNameKeyPath, cacheName: nil) | |
super.init() | |
frc.delegate = self | |
} | |
/// Set `tableView.datasource` to `self`, perform fetch and reload table data | |
public func performFetchAndConfigureTableView(tableView: UITableView) { | |
self.tableView = tableView | |
tableView.dataSource = self | |
do { | |
try frc.performFetch() | |
dispatch_async(dispatch_get_main_queue()) { tableView.reloadData() } | |
} catch { | |
assertionFailure("\(#function): \(error)") | |
} | |
} | |
public func objectAtIndexPath(indexPath: NSIndexPath) -> AnyObject { | |
return frc.objectAtIndexPath(indexPath) | |
} | |
public func titleForHeaderInSection(section: Int) -> String? { | |
return self.frc.sections?[section].name | |
} | |
// MARK: - UITableViewDataSource | |
public func numberOfSectionsInTableView(tableView: UITableView) -> Int { | |
return self.frc.sections?.count ?? 0 | |
} | |
public func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { | |
guard let sections = frc.sections else { return 0 } | |
return sections[section].numberOfObjects | |
} | |
public func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { | |
if let delegate = delegate { | |
return delegate.tableView(tableView, cellForRowAtIndexPath: indexPath, object: self.objectAtIndexPath(indexPath)) | |
} else { | |
assertionFailure("Delegate is not set, can't return cell") | |
return UITableViewCell() | |
} | |
} | |
// func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? { | |
// return self.frc.sections?[section].name | |
// } | |
// MARK: - Right section titles | |
// func tableView(tableView: UITableView, sectionForSectionIndexTitle title: String, atIndex index: Int) -> Int { | |
// return self.frc.sectionForSectionIndexTitle(title, atIndex: index) ?? 0 | |
// } | |
// | |
// func sectionIndexTitlesForTableView(tableView: UITableView) -> [String]? { | |
// return self.frc.sectionIndexTitles | |
// } | |
// MARK: - NSFetchedResultsControllerDelegate | |
public func controllerWillChangeContent(controller: NSFetchedResultsController) { | |
tableView?.beginUpdates() | |
} | |
public func controller(controller: NSFetchedResultsController, didChangeSection sectionInfo: NSFetchedResultsSectionInfo, atIndex sectionIndex: Int, forChangeType type: NSFetchedResultsChangeType) { | |
let sectionIndexSet = NSIndexSet(index: sectionIndex) | |
switch type { | |
case NSFetchedResultsChangeType.Insert: | |
tableView?.insertSections(sectionIndexSet, withRowAnimation: .Automatic) | |
case NSFetchedResultsChangeType.Delete: | |
tableView?.deleteSections(sectionIndexSet, withRowAnimation: .Automatic) | |
case .Update: | |
tableView?.reloadSections(sectionIndexSet, withRowAnimation: .Automatic) | |
case .Move: | |
// TODO: maybe we have better solution instead of reload, possible bugs | |
tableView?.reloadSections(sectionIndexSet, withRowAnimation: .Automatic) | |
} | |
} | |
public func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) { | |
switch type { | |
case .Insert: | |
guard let newIndexPath = newIndexPath else { return } | |
tableView?.insertRowsAtIndexPaths([newIndexPath], withRowAnimation: .Automatic) | |
case .Delete: | |
guard let indexPath = indexPath else { return } | |
tableView?.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Automatic) | |
case .Update: | |
guard let indexPath = indexPath else { return } | |
tableView?.reloadRowsAtIndexPaths([indexPath], withRowAnimation: .Automatic) | |
case .Move: | |
guard let indexPath = indexPath, let newIndexPath = newIndexPath else { return } | |
tableView?.deleteRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Fade) | |
tableView?.insertRowsAtIndexPaths([newIndexPath], withRowAnimation: UITableViewRowAnimation.Fade) | |
} | |
} | |
public func controllerDidChangeContent(controller: NSFetchedResultsController) { | |
tableView?.endUpdates() | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment