update tutorial query existing example enable data adding core-data swift nsmanagedobject

core data - tutorial - Usando protocolos Swift con genéricos



swift 4 core data tutorial (2)

Tengo un ejemplo simple que parece que debería funcionar:

import CoreData @objc protocol CoreDataModel { @optional class func entityName() -> String } class AbstractModel: NSManagedObject, CoreDataModel { class func create<T : CoreDataModel>(context:NSManagedObjectContext) -> T { var name = T.entityName?() var object = NSEntityDescription.insertNewObjectForEntityForName(name, inManagedObjectContext: context) as T return object } }

Entonces, tenemos una clase llamada AbstractModel que se ajusta al protocolo CoreDataModel , y CoreDataModel define un método de clase opcional llamado entityName .

Sin embargo, esta línea:

var name = T.entityName?()

causa el error:

Nombre de miembro esperado o llamada de constructor después del nombre de tipo

¿Alguna idea de lo que estoy haciendo mal?

Editar

Eliminar la palabra @optional de la declaración y cambiar la función un poco permite que el código se compile, pero ahora recibo un error de tiempo de ejecución que indica que el

''Falló el lanzamiento dinámico de Swift''

@objc protocol CoreDataModel { class func entityName() -> String } class AbstractModel: NSManagedObject, CoreDataModel { class func entityName() -> String { return "AbstractModel" } class func create<T : CoreDataModel>(aClass:T.Type, context:NSManagedObjectContext) -> T { var name = aClass.entityName() var object = NSEntityDescription.insertNewObjectForEntityForName(name, inManagedObjectContext: context) as T return object } }


De "El lenguaje de programación Swift"

Como T es un marcador de posición, Swift no busca un tipo real llamado T.

Como T no es un tipo real, tal vez no sea útil lanzarlo a T.


No puedo explicar por qué tu código causa una excepción de tiempo de ejecución. Pero funciona si cambias el prototipo de la función

class func create<T : CoreDataModel>(aClass:T.Type, context:NSManagedObjectContext) -> T

a

class func create<T : NSManagedObject where T: CoreDataModel>(aClass:T.Type, context:NSManagedObjectContext) -> T

Suponiendo que su subclase de objeto gestionado se ajusta al protocolo, por ejemplo

extension Event : CoreDataModel { class func entityName() -> String { return "Event" } }

entonces esto funciona y crea un nuevo objeto:

let newManagedObject = AbstractModel.create(Event.self, context: context)

Alternativamente, puede usar el enfoque de la respuesta a " Swift: return Array of type self " y definir una extensión a la clase NSManagedObjectContext :

extension NSManagedObjectContext { func create<T : NSManagedObject where T : CoreDataModel >(entity: T.Type) -> T { var classname = entity.entityName() var object = NSEntityDescription.insertNewObjectForEntityForName(classname, inManagedObjectContext: self) as T return object } }

Entonces se crearía un nuevo objeto como

let newManagedObject = context.create(Event.self)