// // ItemsViewController.swift // Reader // // Created by Shadowfacts on 1/9/22. // import UIKit import CoreData class ItemsViewController: UIViewController { let fervorController: FervorController let fetchRequest: NSFetchRequest private var collectionView: UICollectionView! private var dataSource: UICollectionViewDiffableDataSource! private var resultsController: NSFetchedResultsController! init(fetchRequest: NSFetchRequest, fervorController: FervorController) { self.fervorController = fervorController self.fetchRequest = fetchRequest super.init(nibName: nil, bundle: nil) } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } override func viewDidLoad() { super.viewDidLoad() var configuration = UICollectionLayoutListConfiguration(appearance: .plain) configuration.backgroundColor = .appBackground let layout = UICollectionViewCompositionalLayout.list(using: configuration) collectionView = UICollectionView(frame: view.bounds, collectionViewLayout: layout) collectionView.delegate = self collectionView.autoresizingMask = [.flexibleWidth, .flexibleHeight] collectionView.register(ItemCollectionViewCell.self, forCellWithReuseIdentifier: "itemCell") view.addSubview(collectionView) dataSource = createDataSource() var snapshot = NSDiffableDataSourceSnapshot() snapshot.appendSections([.items]) dataSource.apply(snapshot, animatingDifferences: false) fetchRequest.sortDescriptors = [NSSortDescriptor(key: "published", ascending: false)] resultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: fervorController.persistentContainer.viewContext, sectionNameKeyPath: nil, cacheName: nil) resultsController.delegate = self try! resultsController.performFetch() } private func createDataSource() -> UICollectionViewDiffableDataSource { let itemCell = UICollectionView.CellRegistration { cell, indexPath, item in cell.updateUI(item: item) } let dataSource = UICollectionViewDiffableDataSource(collectionView: collectionView) { collectionView, indexPath, item in return collectionView.dequeueConfiguredReusableCell(using: itemCell, for: indexPath, item: item) } return dataSource } } extension ItemsViewController { enum Section: Hashable { case items } } extension ItemsViewController: NSFetchedResultsControllerDelegate { func controller(_ controller: NSFetchedResultsController, didChangeContentWith snapshot: NSDiffableDataSourceSnapshotReference) { var snapshot = self.dataSource.snapshot() snapshot.deleteItems(snapshot.itemIdentifiers(inSection: .items)) // use resultsController here instead of controller so we don't have to cast snapshot.appendItems(resultsController.fetchedObjects!, toSection: .items) self.dataSource.apply(snapshot, animatingDifferences: false) } } extension ItemsViewController: UICollectionViewDelegate { func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { guard let item = dataSource.itemIdentifier(for: indexPath) else { return } let vc = ReadViewController(item: item, fervorController: fervorController) show(vc, sender: nil) } }