CoreData: advertencia: no se puede cargar la clase nombrada

94

Estoy duplicando una aplicación de programa de televisión Objective-C existente en una nueva versión de Swift usando Xcode 6.1 y tengo algunos problemas con CoreData.

Creé un modelo de 4 entidades, creé su subclase NSManagedObject (en Swift), y todos los archivos tienen los objetivos de aplicación adecuados establecidos (para 'Compilar fuentes').

Sigo recibiendo este error cada vez que intento insertar una nueva entidad:

CoreData: advertencia: no se puede cargar la clase denominada 'Shows' para la entidad 'Shows'. Clase no encontrada, usando NSManagedObject predeterminado en su lugar.

Algunos comentarios:

Al guardar en Core Data, utilizo la forma de contexto padre-hijo para permitir subprocesos en segundo plano. Hago esto configurando ManagedObjectContext usando:

lazy var managedObjectContext: NSManagedObjectContext? = {
  // Returns the managed object context for the application (which is already bound to the persistent store coordinator for the application.) This property is optional since there are legitimate error conditions that could cause the creation of the context to fail.
  let coordinator = self.persistentStoreCoordinator
  if coordinator == nil {
    return nil
  }
  var managedObjectContext = NSManagedObjectContext(concurrencyType: NSManagedObjectContextConcurrencyType.MainQueueConcurrencyType)
  managedObjectContext.persistentStoreCoordinator = coordinator
  return managedObjectContext
}()

y guardando datos usando:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), { () -> Void in
  var context = NSManagedObjectContext(concurrencyType: NSManagedObjectContextConcurrencyType.PrivateQueueConcurrencyType)
  context.parentContext = self.managedObjectContext!
  ...rest of core data saving code here...
})
JimmyJammed
fuente

Respuestas:

177

Esta advertencia es una de las peculiaridades con las que tenemos que lidiar mientras se resuelven los detalles de la implementación de Swift. La advertencia se produce de forma falsa, es decir, su configuración podría funcionar incluso si no sigue los pasos descritos a continuación.

He podido deshacerme de él en la mayoría de los casos asegurándome de que la clase esté configurada correctamente en el editor de modelos . A diferencia de muchas otras publicaciones de SOF (incluidas las respuestas a esta pregunta), la sugerencia de incluir el nombre del módulo (como MyApp.Shows) no me ha ayudado.

Asegúrese de marcar estos tres elementos:

1.
Versión que funciona hasta Xcode 7 beta 3

Hasta XCode7 b3

Observe que corrigí el nombre de su entidad al singular más apropiado.

Versión que funciona para Swift 2.0 en Xcode 7.1
(debería funcionar para Xcode 7 beta 4 y superior)

Debe eliminar el texto "Módulo de producto actual" en el módulo.

Desde Xcode7 beta 3

2.
También debe seguir la recomendación frecuente de incluir

@objc(Show)

justo encima de tu clase.

Nota : Si está utilizando Xcode 7 beta 4 o posterior, este paso es opcional.

3.
También asegúrese de convertir el objeto administrado creado a la clase adecuada, ya que el valor predeterminado sería just NSManagedObject.

var newShow = NSEntityDescription.insertNewObjectForEntityForName("Show", 
                 inManagedObjectContext: context) as Show
Mundi
fuente
3
¡Gracias! Hice las actualizaciones recomendadas de la convención de nomenclatura, y fue el '@objc (Show)' el que parece hacer el truco para solucionar el error 'No se puede cargar la clase ...'. ¡Muy apreciado!
JimmyJammed
Hola @Mundi. Muchas gracias! ¿Todavía recordarías dónde estaba la fuente?
iamdavidlam
1
Consulte, por ejemplo, esta pregunta . Allí hay suficiente información para comprender lo que está pasando.
Mundi
4
Curiosamente, tuve que eliminar @objc(MyClass)
Santa Claus
1
@Mundi, es posible que desee actualizar su respuesta nuevamente. Vea la actualización de respuestas de khunshan.
Suragch
75

Actualización de SWIFT 2 / XCODE 7:

Este problema (consulte mi comentario del 3 de abril sobre esta respuesta también) se resuelve en la versión beta de Swift 2 y XCode 7 de Apple. Por lo tanto, ahora no necesita @objc(myEntity)en Swift como respondió Mundi o usar " MyAppName." antes de su nombre de clase. Dejará de funcionar. Así que elimínelos, solo ponga el Classnombre en Archivo y seleccione Current Working Modulecomo Módulo y ¡salud!

Selección del módulo de trabajo actual

Pero para aquellos que usan @objc(myEntity)Swift (como yo), pueden usar esta otra solución que funciona sin problemas.

En la clase correcta de xcdatamodel. Debería verse así:

Establecer la clase

Aqui tienes. Module.Classes el patrón para CoreData en Swift y XCode 6. También necesitará el mismo procedimiento cuando use la clase Política personalizada en Política modelo u otras cosas de CoreData. Una nota: en la imagen, el nombre y la clase deben ser Car y MyAppName.Car (o cualquiera que sea el nombre de su entidad). Aquí Userhay un error tipográfico.

Khunshan
fuente
El problema con esta solución es que las clases de entidad de generación automática ya no funcionarán correctamente (generará solo una clase con el nombre del módulo). Consulte: Crear subclase NSManagedObject que no se genera correctamente .
milos
Debe aplicar la solución después de generar clases de entidad NSManagedObject. Probablemente se deba eliminar un error de xcode 6.xx.
khunshan
2
Sí, esto sin duda se resolverá. Las clases generadas automáticamente ya deberían estar adornadas con @objc (<nombre de clase como se ingresó en el inspector de entidades>) o, más probablemente, Apple hará que esto sea innecesario para empezar.
milos
2
Para la gente que todavía lee esto. usar ' MyAppName.Car ' no funcionó para mí, sí funcionó cuando eliminé el ' MyAppName. 'parte. Así que solo Carpara ambos campos funcionó.
Gideon
1
tu Campeón !!!! let person = NSEntityDescription.insertNewObject (forEntityName: "Person", into: context) como! Persona
Abhimanyu Rathore
36

Al usar Xcode 7 y puramente Swift, en realidad tuve que eliminar @objc(MyClass) de mi NSManagedObjectsubclase generada automáticamente (generada desde Editor> Create NSManagedObject Subclass...).

Papá Noel
fuente
4
Wow, gracias por publicar esta respuesta. Estaba a punto de empezar a golpearme la cabeza contra la pared.
Zia
El mismo problema aquí - Enviado un error.
MirekE
También funcionó para mí. Tuve que quitarlo. Extraño.
Kent
Según mis experimentos, parece un falso positivo.
Mundi
Tuve que eliminarlo y configurar el Módulo de producto actual, solo entonces funcionó
Oleg Sherman
13

En Xcode 7 beta 2 (y creo que 1), en la configuración del modelo se establece un nuevo objeto administrado de tipo Fileen el Módulo Current Product Moduley la clase del objeto se muestra en la configuración como .File.

Módulo de tipo de objeto gestionado establecido en "Módulo de producto actual" en Xcode 7

Eliminar la configuración del módulo para que quede en blanco, o eliminar el punto final para que el nombre de la clase en la configuración sea solo Fileacciones equivalentes, ya que cada una provoca el otro cambio. Guardar esta configuración eliminará el error descrito.

Módulo de objeto administrado configurado para estar en blanco en Xcode 7

Duncan Babbage
fuente
9

En Xcode 6.1.1 no es necesario agregar el atributo @objc ya que la entidad base es un subconjunto de una clase objc (NSManagedObject) (consulte Compatibilidad de tipos Swift . En CoreData se requiere el nombre completo de Module.Class. Tenga en cuenta el módulo name es lo que se establece en Build Settings -> Packaging -> Product Module Name. De forma predeterminada, se establece en $ (PRODUCT_NAME: c99extidentifier), que será el nombre del objetivo .

Jim Malak
fuente
¡Si! Esta es la respuesta moderna (xcode 6.3.2). Usar el nombre correcto del paquete es clave. En mi caso, se había transformado my-producten my_producty esto marcó la diferencia en Core Data.
SimplGy
5

Con xCode 7 y la versión Swift 2.0, no necesita agregar @objc (NameOfClass), simplemente cambie la configuración de la entidad en la pestaña "Mostrar el inspector del modelo de datos" como se muestra a continuación:

Nombre: "Nombre de su entidad"

Clase: "Nombre de su entidad"

Módulo - "Módulo de producto actual"

ingrese la descripción de la imagen aquí

El código para el archivo de clase de entidad será como (en mi código, la entidad es familia):

import UIKit
import CoreData

class Family: NSManagedObject {

   @NSManaged var member : AnyObject
}

Este ejemplo funciona bien en mi aplicación con xCode 7.0 + swift 2.0

Himanshu Mahajan
fuente
3

No olvide reemplazar PRODUCT_MODULE_NAMEcon el nombre del módulo de su producto.

Cuando se crea una nueva entidad, debe ir al Inspector del modelo de datos (última pestaña) y reemplazar PRODUCT_MODULE_NAMEcon el nombre de su módulo, o resultará un class not founderror al crear el coordinador de tienda persistente.

Kof
fuente
2

También necesita usar (al menos con Xcode 6.3.2) Module.Class al realizar su lanzamiento, por ejemplo: asumiendo que su módulo (es decir, el nombre del producto) es Comida y su clase es Fruta

let myEntity =  NSEntityDescription.entityForName("Fruit", inManagedObjectContext: managedContext)

let fruit = NSManagedObject(entity: myEntity!, insertIntoManagedObjectContext:managedContext) as! Food.Fruit

Resumen:

  • Incluya el nombre del módulo al definir la entidad en el Editor de modelos de datos (Nombre: Fruta, Clase: Comida, Fruta)
  • Al acceder a la entidad en código (ieSWIFT), conviértalo con Module.class (por ejemplo, Food.Fruit)
Wizkid
fuente
Gracias, el segundo punto es muy importante. Tuve que usar "Module.Class" al lanzarlo.
Zoyt
1

Cambiar el nombre de la clase de entidad en el editor del modelo de datos para que se corresponda con la clase en cuestión y agregarlo @objc(NameOfClass)al archivo de cada NSManagedObject justo encima de la declaración de clase me resolvió este problema durante las pruebas unitarias.

user3269767
fuente
0

Lo que funcionó para mí (Xcode 7.4, Swift) es cambiar el nombre de la clase a <my actual class name>.<entity name> en el inspector de entidades, cuadro 'Clase'.

Mi iniciador de la subclase de objetos administrados se ve así:

    convenience init(<properties to init>) {
    let entityDescr = NSEntityDescription.entityForName("<entity class name>", inManagedObjectContext: <managed context>)
    self.init(entity: entityDescr!, insertIntoManagedObjectContext: <managed context>)}
    //init properties here
marca
fuente
0

Para Xcode 11.5: si la propiedad Codegen es la definición de clase y si no recibe una sugerencia para la entidad que creó en xcdatamodel. Intente salir de Xcode y vuelva a abrir su proyecto. Esto funciona para mi. Esta respuesta es solo si no recibe sugerencias, pero si su archivo no se genera, intente cualquiera de las respuestas anteriores.

Gulshan Kumar
fuente