CoreData: avviso: impossibile caricare la classe denominata


94

Sto duplicando un'app Objective-C TV Show esistente su una nuova versione di Swift utilizzando Xcode 6.1 e sto riscontrando alcuni problemi con CoreData.

Ho creato un modello di 4 entità, creato la loro sottoclasse NSManagedObject (in Swift) e tutti i file hanno gli obiettivi di app corretti impostati (per "Compile Sources").

Continuo a ricevere questo errore ogni volta che provo a inserire una nuova entità:

CoreData: avviso: impossibile caricare la classe denominata "Spettacoli" per l'entità "Spettacoli". Classe non trovata, utilizzando invece NSManagedObject predefinito.

Alcuni commenti:

Durante il salvataggio in Core Data, utilizzo il modo del contesto padre-figlio per consentire il threading in background. Lo faccio impostando 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
}()

e salvando i dati utilizzando:

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...
})

Risposte:


177

Questo avvertimento è una delle stranezze che dobbiamo affrontare mentre vengono risolti i dettagli dell'implementazione di Swift. L'avviso si verifica in modo errato, ovvero la configurazione potrebbe funzionare anche se non si seguono i passaggi descritti di seguito.

Sono stato in grado di eliminarlo nella maggior parte dei casi assicurandomi che la classe sia impostata correttamente nell'editor del modello . A differenza di molti altri post SOF (comprese le risposte a questa domanda), il suggerimento di includere il nome del modulo (come MyApp.Shows) non mi ha aiutato.

Assicurati di controllare questi tre elementi:

1.
Versione che funziona fino a Xcode 7 beta 3

Fino a XCode7 b3

Nota che ho corretto il nome della tua entità al singolare più appropriato.

Versione che funziona per Swift 2.0 in Xcode 7.1
(dovrebbe funzionare per Xcode 7 beta 4 e versioni successive)

È necessario eliminare il testo "Modulo prodotto corrente" nel modulo!

Da Xcode7 beta 3

2.
Dovresti anche seguire la frequente raccomandazione di includere

@objc(Show)

appena sopra la tua classe.

Nota : se utilizzi Xcode 7 beta 4 o versioni successive, questo passaggio è facoltativo.

3.
Assicurarsi inoltre di eseguire il cast dell'oggetto gestito creato nella classe appropriata, poiché l'impostazione predefinita sarebbe just NSManagedObject.

var newShow = NSEntityDescription.insertNewObjectForEntityForName("Show", 
                 inManagedObjectContext: context) as Show

3
Grazie! Ho apportato gli aggiornamenti della convenzione di denominazione consigliati ed è stato "@objc (Show)" che sembra fare il trucco per correggere l'errore "Impossibile caricare la classe ...". Molto apprezzato!
JimmyJammed il

Ciao @Mundi. Grazie mille! ricorderesti ancora dov'era la fonte?
iamdavidlam

1
Vedi ad esempio questa domanda . Ci sono abbastanza informazioni per capire cosa sta succedendo.
Mundi

4
È interessante notare che ho dovuto rimuovere @objc(MyClass)
Babbo Natale il

1
@ Mundi, potresti voler aggiornare di nuovo la tua risposta. Vedi l'aggiornamento della risposta di khunshan.
Suragch

75

Aggiornamento SWIFT 2 / XCODE 7:

Questo problema (vedi anche il mio commento del 3 aprile su questa risposta) è stato risolto in Swift 2 e XCode 7 beta release di Apple. Quindi ora in realtà non è necessario che @objc(myEntity)Swift risponda a Mundi o che usi " MyAppName." prima del nome della classe. Smetterà di funzionare. Quindi rimuovili, metti il Classnome in File e seleziona Current Working Modulecome Modulo e ciao!

Selezione del modulo di lavoro corrente

Ma per quelli che usano @objc(myEntity)in Swift (come me), puoi usare quest'altra soluzione invece che funziona senza problemi.

Nella classe corretta xcdatamodel in. Dovrebbe assomigliare a questo:

Impostazione della classe

Ecco qui. Module.Classè il modello per CoreData in Swift e XCode 6. Avrai anche bisogno della stessa procedura quando usi la classe Custom Policy in Model Policy o altre cose CoreData. Una nota: nell'immagine, il nome e la classe dovrebbero essere Car e MyAppName.Car (o qualunque sia il nome della tua entità). Ecco Userun errore di battitura.


Il problema con questa soluzione è che la generazione automatica delle classi di entità non funzionerà più correttamente (genererà solo una classe con il nome del modulo). Vedere: Creazione di una sottoclasse NSManagedObject non generata correttamente .
milos

È necessario applicare la soluzione dopo aver generato le classi di entità NSManagedObject. Probabilmente un bug di xcode 6.xx da rimuovere.
Khunshan

2
Sì, questo sarà senza dubbio risolto. Le classi generate automaticamente dovrebbero essere già adornate con @objc (<nome della classe come inserito in Entity Inspector>) o, più probabilmente, Apple lo renderà superfluo per cominciare.
milos

2
Per le persone che stanno ancora leggendo questo. utilizzando ' MyAppName.Car ' non ha funzionato per me, ha funzionato quando ho rimosso il ' MyAppName. ' parte. Quindi solo Carper entrambi i campi ha funzionato.
Gideon

1
tu Campione !!!! let person = NSEntityDescription.insertNewObject (forEntityName: "Person", into: context) as! Persona
Abhimanyu Rathore

36

Quando si utilizza Xcode 7 e puramente Swift, in realtà ho dovuto rimuovere @objc(MyClass) dalla mia NSManagedObjectsottoclasse generata automaticamente (generata da Editor> Create NSManagedObject Subclass...).


4
Wow, grazie per aver pubblicato questa risposta. Stavo per iniziare a sbattere la testa contro il muro.
Zia

Stesso problema qui - Presentato un bug.
MirekE

Ha funzionato anche per me. Ho dovuto rimuoverlo. Bizzarro.
Kent

Secondo i miei esperimenti sembra un falso positivo.
Mundi

Ho dovuto rimuoverlo e impostare Current Product Module, solo allora ha funzionato
Oleg Sherman

13

In Xcode 7 beta 2 (e credo 1), nella configurazione del modello un nuovo oggetto gestito di tipo Fileè impostato sul Modulo Current Product Modulee la classe dell'oggetto è mostrata nella configurazione come .File.

Modulo del tipo di oggetto gestito impostato su "Modulo prodotto corrente" in Xcode 7

Eliminare l'impostazione del modulo in modo che sia vuoto o rimuovere il punto in modo che il nome della classe nella configurazione sia solo Fileazioni equivalenti, poiché ciascuna causa l'altra modifica. Il salvataggio di questa configurazione rimuoverà l'errore descritto.

Il modulo dell'oggetto gestito deve essere vuoto in Xcode 7


9

In Xcode 6.1.1 non è necessario aggiungere l'attributo @objc poiché l'entità di base è un sottoinsieme di una classe objc (NSManagedObject) (vedere Swift Type Compatibility . In CoreData è richiesto il nome completo di Module.Class. Tenere presente il Module nome è ciò che è impostato in Impostazioni build -> Confezione -> Nome modulo prodotto. Per impostazione predefinita, è impostato su $ (PRODUCT_NAME: c99extidentifier) ​​che sarà il nome del target .


Sì! Questa è la risposta moderna (xcode 6.3.2). L'utilizzo del nome del pacchetto corretto è la chiave. Nel mio caso, si era trasformato my-productin my_product, e questo ha fatto la differenza per Core Data.
SimplGy

5

Con xCode 7 e la versione Swift 2.0, non è necessario aggiungere @objc (NameOfClass), basta modificare le impostazioni dell'entità nella scheda "Mostra l'ispettore modello dati" come di seguito -

Nome - "Nome dell'entità"

Classe - "Nome dell'entità"

Modulo - "Modulo prodotto corrente"

inserisci qui la descrizione dell'immagine

Il file di classe Code for Entity sarà come (nel mio codice Entity is Family) -

import UIKit
import CoreData

class Family: NSManagedObject {

   @NSManaged var member : AnyObject
}

Questo esempio funziona bene nella mia app con xCode 7.0 + swift 2.0


3

Non dimenticare di sostituire PRODUCT_MODULE_NAMEcon il nome del modulo del tuo prodotto.

Quando viene creata una nuova entità, è necessario andare al Data Model Inspector (ultima scheda) e sostituirla PRODUCT_MODULE_NAMEcon il nome del modulo, altrimenti si verificherà un class not founderrore durante la creazione del coordinatore del negozio persistente.


2

Devi anche usare (almeno con Xcode 6.3.2) Module.Class quando esegui il cast, ad esempio: supponendo che il tuo modulo (cioè il nome del prodotto) sia Food e la tua classe sia Fruit

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

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

Ricapitolare:

  • Includere il nome del modulo quando si definisce l'entità nell'editor del modello di dati (nome: frutta, classe: cibo.frutta)
  • Quando si accede all'entità in codice (cioè SWIFT), lanciarla con Module.class (ad esempio Food.Fruit)

Grazie, il secondo punto è molto importante. Ho dovuto usare "Module.Class" durante il casting.
Zoyt


1

La modifica del nome della classe di entità nell'editor del modello di dati in modo che corrisponda alla classe in questione e l'aggiunta @objc(NameOfClass)al file di ogni NSManagedObject proprio sopra la dichiarazione della classe mi ha risolto questo problema durante gli unit test.


0

Ciò che ha funzionato per me (Xcode 7.4, Swift) è stato modificare il nome della classe <my actual class name>.<entity name> in Impostazioni entità, casella "Classe".

Il mio iniziatore della sottoclasse di oggetti gestiti, ha questo aspetto:

    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

0

Per Xcode 11.5: se la proprietà Codegen è class Definition e se non ricevi un suggerimento per l'entità che hai creato in xcdatamodel. Prova a chiudere Xcode e riapri di nuovo il tuo progetto. Per me funziona. Questa risposta è solo se non ricevi suggerimenti, ma se il tuo file non viene generato, prova una delle risposte precedenti.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.