Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create a generic Swift function to return an array of Core Data entities

Caveat: I am still pretty new to both Swift and Core Data

I have several functions in my code that return an array of a specific entity type:

func fetchStores() -> [Store]? {
  var stores: [Store]?
  let fetchRequest: NSFetchRequest<Store> = Store.fetchRequest()

  do {
    stores = try ad.persistentContainer.viewContext.fetch(fetchRequest)
  } catch {
    assert(false, error.localizedDescription)
  }

  return stores
}

I'd like to create a generic function that handles all of my entities:

func fetchEntities<T: NSManagedObject>(entity: T) -> [T]? {
  var results: [T]?

  if let fetchRequest: NSFetchRequest<T> = T.fetchRequest() as? NSFetchRequest<T> {
    do {
      results = try ad.persistentContainer.viewContext.fetch(fetchRequest)
    } catch  {
      assert(false, error.localizedDescription)
    }
  } else {
    assert(false,"Error: cast to NSFetchRequest<T> failed")
  }

  return results
}

// Usage:
let store = Store()
let stores = fetchEntities(entity: store)

Is there a way for me to do this without having to create a Store instance?

TIA

like image 284
RobertJoseph Avatar asked Dec 24 '22 20:12

RobertJoseph


2 Answers

You were almost there. You only have to change the parameter type from T to T.Type:

func fetchEntities<T: NSManagedObject>(entity: T.Type) -> [T]?

so that you can pass a type instead of an instance:

let stores = fetchEntities(entity: Store.self)
like image 83
Martin R Avatar answered May 18 '23 19:05

Martin R


I was having exactly the same problem and even Martin's answer didn't work for me. How I ended up solving was to use:

let entityName = String(describing: T.self)
let fetchRequest: NSFetchRequest<T> = NSFetchRequest(entityName: entityName)

instead of the iOS 10 class function and it worked perfectly fine.

like image 29
Rodrigo Escobar Avatar answered May 18 '23 20:05

Rodrigo Escobar