Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to write a simple generic Core Data function for all Entities

EDIT: Specifically using Swift Generics

I want a countAll() function for all of my entities and I'm hoping to achieve this by writing one generic function.

The following handles an entity called 'Event', but I want to handle an entity named 'T'.

I'm not sure how to write a generic function like this. Could someone help please?

func countAll() -> Int {
    let request: NSFetchRequest<Event> = Event.fetchRequest()
    do {
      return try persistentContainer.viewContext.count(for: request)
    } catch {
      XCTAssert(false, "Core Data failed to fetch with error: " + error.localizedDescription)
      return 0
    }
}

This is the closest I can get before I hit an error:

func count<T: NSFetchRequestResult>(entityName: String) -> Int {
    let request = NSFetchRequest<T>(entityName: entityName)
    do {
      return try persistentContainer.viewContext.count(for: request)
    } catch {
      XCTAssert(false, "Core Data failed to fetch with error: " + error.localizedDescription)
      return 0
    }
}

1 Answers

You can pass the managed object class instead of NSFetchRequestResult to the generic function:

func countAll<T: NSManagedObject>(entity: T.Type) -> Int {
    let entityName = String(describing: entity)
    let request = NSFetchRequest<T>(entityName: entityName)
    do {
        return try thePersistentContainer.viewContext.count(for: request)
    } catch {
        print(error.localizedDescription)
        return 0
    }
}

let count = countAll(entity: YourEntity.self)

An alternative is to define an extension method on NSManagedObject (similarly as in How can I create instances of managed object subclasses in a NSManagedObject Swift extension?):

extension NSManagedObject {

    class func countAll() -> Int {
        let eName = String(describing: self)
        let request = NSFetchRequest<NSFetchRequestResult>(entityName: eName)
        do {
            return try thePersistentContainer.viewContext.count(for: request)
        } catch {
            print(error.localizedDescription)
            return 0
        }
    }
}

let count = YourEntity.countAll()
like image 72
Martin R Avatar answered Oct 29 '25 04:10

Martin R



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!