¿Cómo aplicar el tipo a una instancia de NSFetchRequest?

En Swift 2 el siguiente código estaba funcionando:

let request = NSFetchRequest(entityName: String) 

pero en Swift 3 da error:

El parámetro genérico “ResultType” no se pudo inferir

porque NSFetchRequest es ahora un tipo genérico. En sus documentos, escribieron esto:

 let request: NSFetchRequest = Animal.fetchRequest 

Entonces, si mi clase de resultado es, por ejemplo, Level ¿cómo debo solicitarla correctamente?

Porque esto no funciona:

 let request: NSFetchRequest = Level.fetchRequest 

 let request: NSFetchRequest = Level.fetchRequest() 

o

 let request: NSFetchRequest = Level.fetchRequest() 

dependiendo de la versión que quieras.

Debe especificar el tipo genérico porque, de lo contrario, la llamada al método es ambigua.

La primera versión se define para NSManagedObject , la segunda versión se genera automáticamente para cada objeto que utiliza una extensión, por ejemplo:

 extension Level { @nonobjc class func fetchRequest() -> NSFetchRequest { return NSFetchRequest(entityName: "Level"); } @NSManaged var timeStamp: NSDate? } 

El objective es eliminar el uso de constantes de cadena.

Creo que lo hice funcionar al hacer esto:

 let request:NSFetchRequest = NSFetchRequest(entityName: "Level") 

al menos guarda y carga datos de DataBase.

Pero parece que no es una solución adecuada, pero funciona por ahora.

La estructura más simple que encontré que funciona en 3.0 es la siguiente:

 let request = NSFetchRequest(entityName: "Country") 

donde la entidad de datos Tipo es País.

Sin embargo, al tratar de crear un Core Data BatchDeleteRequest, encontré que esta definición no funciona y parece que tendrá que ir con el formulario:

 let request: NSFetchRequest = Country.fetchRequest() 

aunque se supone que los formatos ManagedObject y FetchRequestResult son equivalentes.

Aquí hay algunos métodos generics de CoreData que podrían responder a su pregunta:

 import Foundation import Cocoa func addRecord(_ type : T.Type) -> T { let entityName = T.description() let context = app.managedObjectContext let entity = NSEntityDescription.entity(forEntityName: entityName, in: context) let record = T(entity: entity!, insertInto: context) return record } func recordsInTable(_ type : T.Type) -> Int { let recs = allRecords(T.self) return recs.count } func allRecords(_ type : T.Type, sort: NSSortDescriptor? = nil) -> [T] { let context = app.managedObjectContext let request = T.fetchRequest() do { let results = try context.fetch(request) return results as! [T] } catch { print("Error with request: \(error)") return [] } } func query(_ type : T.Type, search: NSPredicate?, sort: NSSortDescriptor? = nil, multiSort: [NSSortDescriptor]? = nil) -> [T] { let context = app.managedObjectContext let request = T.fetchRequest() if let predicate = search { request.predicate = predicate } if let sortDescriptors = multiSort { request.sortDescriptors = sortDescriptors } else if let sortDescriptor = sort { request.sortDescriptors = [sortDescriptor] } do { let results = try context.fetch(request) return results as! [T] } catch { print("Error with request: \(error)") return [] } } func deleteRecord(_ object: NSManagedObject) { let context = app.managedObjectContext context.delete(object) } func deleteRecords(_ type : T.Type, search: NSPredicate? = nil) { let context = app.managedObjectContext let results = query(T.self, search: search) for record in results { context.delete(record) } } func saveDatabase() { let context = app.managedObjectContext do { try context.save() } catch { print("Error saving database: \(error)") } } 

Suponiendo que hay una configuración de NSManagedObject para Contact como esta:

 class Contact: NSManagedObject { @NSManaged var contactNo: Int @NSManaged var contactName: String } 

Estos métodos se pueden usar de la siguiente manera:

 let name = "John Appleseed" let newContact = addRecord(Contact.self) newContact.contactNo = 1 newContact.contactName = name let contacts = query(Contact.self, search: NSPredicate(format: "contactName == %@", name)) for contact in contacts { print ("Contact name = \(contact.contactName), no = \(contact.contactNo)") } deleteRecords(Contact.self, search: NSPredicate(format: "contactName == %@", name)) recs = recordsInTable(Contact.self) print ("Contacts table has \(recs) records") saveDatabase() 

Esta es la forma más sencilla de migrar a Swift 3.0, solo agrega

(probado y trabajado)

 let request = NSFetchRequest(entityName: "Country") 

También tuve “ResultType” no se pudo inferir errores. Se borraron una vez que reconstruí el modelo de datos estableciendo el Codegen de cada entidad en “Definición de clase”. Hice una breve descripción con instrucciones paso a paso aquí:

Buscando un tutorial claro sobre NSPersistentContainer revisado en Xcode 8 con Swift 3

Por “reconstruido” quiero decir que creé un nuevo archivo de modelo con nuevas entradas y atributos. Un poco tedioso, pero funcionó!

Lo que funcionó mejor para mí hasta ahora fue:

 let request = Level.fetchRequest() as! NSFetchRequest 

Tuve el mismo problema y lo resolví con los siguientes pasos:

  • Seleccione su archivo xcdatamodeld y vaya al inspector de modelo de datos
  • Seleccione su primera entidad y vaya a la clase de sección
  • Asegúrese de que Codegen “Class Definition” esté seleccionado.
  • Elimine todos los archivos de Entidad generados. Ya no los necesitas más.

Después de hacer eso tuve que eliminar / reescribir todas las ocurrencias de fetchRequest como XCode parece que de alguna manera se mezcla con la versión generada por código.

HTH

Swift 3.0 Esto debería funcionar.

 let request: NSFetchRequest = NSManagedObject.fetchRequest() request.entity = entityDescription(context) request.predicate = predicate