NSFetchedResultsContollerDelegate for CollectionView

前端 未结 6 1064
悲哀的现实
悲哀的现实 2020-11-30 21:10

I\'d like to use the NSFetchedResultsControllerRelegate in a CollectionViewController. Therefore I just changed the method for the TableViewController for the CollectionView

6条回答
  •  离开以前
    2020-11-30 21:24

    I made @Plot's solution it's own object and converted it to Swift 2

    import Foundation
    import CoreData
    
    class CollectionViewFetchedResultsControllerDelegate: NSObject, NSFetchedResultsControllerDelegate {
    
        // MARK: Properties
    
        private let collectionView: UICollectionView
        private var blockOperations: [NSBlockOperation] = []
    
        // MARK: Init
    
        init(collectionView: UICollectionView) {
            self.collectionView = collectionView
        }
    
        // MARK: Deinit
    
        deinit {
            blockOperations.forEach { $0.cancel() }
            blockOperations.removeAll(keepCapacity: false)
        }
    
        // MARK: NSFetchedResultsControllerDelegate
    
        func controllerWillChangeContent(controller: NSFetchedResultsController) {
            blockOperations.removeAll(keepCapacity: false)
        }
    
        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 }
                let op = NSBlockOperation { [weak self] in self?.collectionView.insertItemsAtIndexPaths([newIndexPath]) }
                blockOperations.append(op)
    
            case .Update:
                guard let newIndexPath = newIndexPath else { return }
                let op = NSBlockOperation { [weak self] in self?.collectionView.reloadItemsAtIndexPaths([newIndexPath]) }
                blockOperations.append(op)
    
            case .Move:
                guard let indexPath = indexPath else { return }
                guard let newIndexPath = newIndexPath else { return }
                let op = NSBlockOperation { [weak self] in self?.collectionView.moveItemAtIndexPath(indexPath, toIndexPath: newIndexPath) }
                blockOperations.append(op)
    
            case .Delete:
                guard let indexPath = indexPath else { return }
                let op = NSBlockOperation { [weak self] in self?.collectionView.deleteItemsAtIndexPaths([indexPath]) }
                blockOperations.append(op)
    
            }
        }
    
        func controller(controller: NSFetchedResultsController, didChangeSection sectionInfo: NSFetchedResultsSectionInfo, atIndex sectionIndex: Int, forChangeType type: NSFetchedResultsChangeType) {
    
            switch type {
    
            case .Insert:
                let op = NSBlockOperation { [weak self] in self?.collectionView.insertSections(NSIndexSet(index: sectionIndex)) }
                blockOperations.append(op)
    
            case .Update:
                let op = NSBlockOperation { [weak self] in self?.collectionView.reloadSections(NSIndexSet(index: sectionIndex)) }
                blockOperations.append(op)
    
            case .Delete:
                let op = NSBlockOperation { [weak self] in self?.collectionView.deleteSections(NSIndexSet(index: sectionIndex)) }
                blockOperations.append(op)
    
            default: break
    
            }
        }
    
        func controllerDidChangeContent(controller: NSFetchedResultsController) {
            collectionView.performBatchUpdates({
                self.blockOperations.forEach { $0.start() }
            }, completion: { finished in
                self.blockOperations.removeAll(keepCapacity: false)
            })
        }
    
    }
    

    Usage:

    fetchedResultsController.delegate = CollectionViewFetchedResultsControllerDelegate(collectionView)
    

    Swift 4 version

    private var blockOperations: [BlockOperation] = []
    
    func controllerWillChangeContent(_ controller: NSFetchedResultsController) {
        blockOperations.removeAll(keepingCapacity: false)
    }
    
    func controller(_ controller: NSFetchedResultsController,
                    didChange anObject: Any,
                    at indexPath: IndexPath?,
                    for type: NSFetchedResultsChangeType,
                    newIndexPath: IndexPath?) {
    
        let op: BlockOperation
        switch type {
        case .insert:
            guard let newIndexPath = newIndexPath else { return }
            op = BlockOperation { self.collectionView.insertItems(at: [newIndexPath]) }
    
        case .delete:
            guard let indexPath = indexPath else { return }
            op = BlockOperation { self.collectionView.deleteItems(at: [indexPath]) }
        case .move:
            guard let indexPath = indexPath,  let newIndexPath = newIndexPath else { return }
            op = BlockOperation { self.collectionView.moveItem(at: indexPath, to: newIndexPath) }
        case .update:
            guard let indexPath = indexPath else { return }
            op = BlockOperation { self.collectionView.reloadItems(at: [indexPath]) }
        }
    
        blockOperations.append(op)
    }
    
    func controllerDidChangeContent(_ controller: NSFetchedResultsController) {
        collectionView.performBatchUpdates({
            self.blockOperations.forEach { $0.start() }
        }, completion: { finished in
            self.blockOperations.removeAll(keepingCapacity: false)
        })
    }
    

提交回复
热议问题