jessesquires / JSQCoreDataKit

A swifter Core Data stack
https://jessesquires.github.io/JSQCoreDataKit/
MIT License
614 stars 69 forks source link

Misc notes on improvements and learnings from ReactiveCollectionsKit #277

Open jessesquires opened 1 month ago

jessesquires commented 1 month ago

At the time of this writing, there are various improvements in-progress. There has not been much activity here for awhile.

The goal of the next big release is to use diffable data sources, etc. See FetchedResultsDiffableDataSource in-progress.

In the meantime, ReactiveCollectionsKit has advanced a lot. There are a lot of learnings there to bring in here regarding diffing.

Notes

Random notes and links. Some of these are old and I don't remember the full context. Anyway, I'm putting them all here for when I finally come back to this project.

jessesquires commented 1 month ago

Potentially useful extensions from elsewhere

import CoreData

extension NSManagedObjectContext {
    func fetchAll<T>(_ request: NSFetchRequest<T>) -> [T] {
        (try? self.fetch(request)) ?? []
    }

    func fetchFirst<T>(_ request: NSFetchRequest<T>) -> T? {
        try? self.fetch(request).first
    }

    func totalCount<T>(_ request: NSFetchRequest<T>) -> Int {
        (try? self.count(for: request)) ?? 0
    }

    func exists<T>(_ request: NSFetchRequest<T>) -> Bool {
        !self.totalCount(request).isZero
    }

    /// Remove all the objects for the provided entities and return the number of objects removed.
    @discardableResult
    func removeAll(entities: [CoreDataEntityName]) throws -> Int {
        let totalCount = try entities.map {
            try self.removeAll($0)
        }
        return totalCount.reduce(0, +)
    }

    /// Remove all the objects for the entity and return the number of objects removed.
    @discardableResult
    func removeAll(_ entity: CoreDataEntityName) throws -> Int {
        let deleteFetch = NSFetchRequest<NSManagedObject>(entityName: entity.name)
        deleteFetch.includesPropertyValues = false
        let results = try self.fetch(deleteFetch)
        self.delete(objects: results)
        return results.count
    }

    /// Deletes the specified objects.
    func delete(objects: [NSManagedObject]) {
        objects.forEach {
            self.delete($0)
        }
    }
}

extension NSFetchedResultsController {
    @objc
    func validate(indexPath: IndexPath) -> Bool {
        if let sections = self.sections,
            indexPath.section < sections.count {
            return indexPath.row < sections[indexPath.section].numberOfObjects
        }
        return false
    }
}