Last active
May 18, 2023 11:53
-
-
Save karthiikmk/870acd93b1ef9a45ffed6866ae40d045 to your computer and use it in GitHub Desktop.
FetchedResultsTableViewController
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
public class FetchedResultsTableViewController<Entity: NSFetchRequestResult, Content: View>: UITableViewController { | |
private let reuseIdentifier = "FetchedResultsCell" | |
private let fetchedResultsController: NSFetchedResultsController<Entity> | |
private var selectionType: SelectionType = .single | |
private var cellSelectionStyle: UITableViewCell.SelectionStyle = .default | |
private let baseQuery: Query<Entity> | |
private var cellContent: (Entity, _ isSelected: Bool) -> Content | |
private var didSelectRow: ((Entity) -> Void)? | |
public init(parentView: FetchedResultsTableViewControllerWrapper<Entity, Content>, context: NSManagedObjectContext) { | |
self.cellContent = parentView.cellContent | |
self.didSelectRow = parentView.didSelectRow | |
self.baseQuery = parentView.query | |
self.selectionType = parentView.selectionType | |
self.cellSelectionStyle = parentView.cellSelectionStyle | |
let entityName = String(describing: Entity.self) | |
let fetchRequest: NSFetchRequest<Entity> = NSFetchRequest<Entity>(entityName: entityName) | |
fetchRequest.sortDescriptors = baseQuery.sortDescriptors | |
fetchRequest.predicate = baseQuerySet.predicate | |
fetchRequest.fetchBatchSize = 20 // | |
self.fetchedResultsController = NSFetchedResultsController( | |
fetchRequest: fetchRequest, | |
managedObjectContext: context, | |
sectionNameKeyPath: nil, | |
cacheName: nil | |
) | |
super.init(style: .plain) | |
} | |
required init?(coder: NSCoder) { | |
fatalError("init(coder:) has not been implemented") | |
} | |
public override func viewDidLoad() { | |
super.viewDidLoad() | |
tableView.register(UITableViewCell.self, forCellReuseIdentifier: reuseIdentifier) | |
tableView.delegate = self | |
tableView.dataSource = self | |
tableView.separatorStyle = .none | |
} | |
// MARK: - Table view data source | |
override public func numberOfSections(in tableView: UITableView) -> Int { | |
return fetchedResultsController.sections?.count ?? 0 | |
} | |
override public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { | |
return fetchedResultsController.sections?[section].numberOfObjects ?? 0 | |
} | |
override public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { | |
let cell = tableView.dequeueReusableCell(withIdentifier: reuseIdentifier, for: indexPath) | |
/// Workaround: Clear subviews from reused cells | |
/// Sometimes old cell weren't clearning out which retained in memory. | |
cell.contentView.subviews.forEach { $0.removeFromSuperview() } | |
cell.selectionStyle = cellSelectionStyle | |
let item = fetchedResultsController.object(at: indexPath) | |
let isItemSelected = selectedEntities.contains(item) | |
let cellContentView = cellContent(item, isItemSelected) | |
let hostingController = UIHostingController(rootView: cellContentView) | |
hostingController.view.frame = cell.contentView.bounds | |
hostingController.view.backgroundColor = .clear | |
hostingController.view.translatesAutoresizingMaskIntoConstraints = false | |
cell.contentView.addSubview(hostingController.view) | |
NSLayoutConstraint.activate([ | |
hostingController.view.leadingAnchor.constraint(equalTo: cell.contentView.leadingAnchor), | |
hostingController.view.trailingAnchor.constraint(equalTo: cell.contentView.trailingAnchor), | |
hostingController.view.topAnchor.constraint(equalTo: cell.contentView.topAnchor), | |
hostingController.view.bottomAnchor.constraint(equalTo: cell.contentView.bottomAnchor) | |
]) | |
hostingController.didMove(toParent: self) | |
return cell | |
} | |
public override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { | |
tableView.deselectRow(at: indexPath, animated: true) | |
} | |
fileprivate func updateQueryIfNeeded(with searchText: String?) { | |
// Update your search query here. | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment