CoreData: Warnung: Die benannte Klasse kann nicht geladen werden

94

Ich dupliziere eine vorhandene Objective-C-TV-Show-App mit Xcode 6.1 auf eine neue Swift-Version und habe einige Probleme mit CoreData.

Ich habe ein Modell von 4 Entitäten erstellt, ihre NSManagedObject-Unterklasse (in Swift) erstellt und für alle Dateien sind die richtigen App-Ziele festgelegt (für 'Quellen kompilieren').

Ich erhalte immer noch diesen Fehler, wenn ich versuche, eine neue Entität einzufügen:

CoreData: Warnung: Klasse mit dem Namen 'Shows' für Entität 'Shows' kann nicht geladen werden. Klasse nicht gefunden, stattdessen Standard-NSManagedObject.

Ein paar Kommentare:

Beim Speichern in Kerndaten verwende ich die Eltern-Kind-Kontextmethode, um Hintergrund-Threading zuzulassen. Dazu richte ich den ManagedObjectContext ein mit:

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

und durch Speichern von Daten mit:

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
quelle

Antworten:

177

Diese Warnung ist eine der Macken, mit denen wir uns befassen müssen, während die Details der Swift-Implementierung ausgebügelt werden. Die Warnung tritt fälschlicherweise auf, dh Ihr Setup funktioniert möglicherweise auch dann, wenn Sie die unten beschriebenen Schritte nicht ausführen.

In den meisten Fällen konnte ich es beseitigen, indem ich sicherstellte, dass die Klasse im Modelleditor richtig eingestellt ist . Anders als in vielen anderen SOF-Posts (einschließlich Antworten auf diese Frage) hat der Vorschlag, den Modulnamen (wie MyApp.Shows) aufzunehmen, dies nicht getan mir geholfen.

Stellen Sie sicher, dass Sie diese drei Punkte überprüfen:

1.
Version, die bis zu Xcode 7 Beta 3 funktioniert

Bis zu XCode7 b3

Beachten Sie, dass ich Ihren Entitätsnamen auf den passenderen Singular korrigiert habe.

Version, die für Swift 2.0 in Xcode 7.1
funktioniert (sollte für Xcode 7 Beta 4 und höher funktionieren)

Sie müssen den Text "Aktuelles Produktmodul" im Modul löschen!

Ab Xcode7 Beta 3

2.
Sie sollten auch die häufige Empfehlung befolgen

@objc(Show)

direkt über deiner Klasse.

Hinweis : Wenn Sie Xcode 7 Beta 4 oder höher verwenden, ist dieser Schritt optional.

3.
Achten Sie außerdem darauf werfen das erstellte verwaltete Objekt in die richtige Klasse, als die Standard nur sein würde NSManagedObject.

var newShow = NSEntityDescription.insertNewObjectForEntityForName("Show", 
                 inManagedObjectContext: context) as Show
Mundi
quelle
3
Vielen Dank! Ich habe die empfohlenen Aktualisierungen der Namenskonvention vorgenommen, und es war das '@objc (Show)', das den Trick bei der Behebung des Fehlers 'Klasse kann nicht geladen werden ...' zu tun scheint. Sehr geschätzt!
JimmyJammed
Hallo @ Mundi. Ich danke dir sehr! Würdest du dich noch daran erinnern, wo die Quelle war?
Iamdavidlam
1
Siehe zB diese Frage . Es gibt dort genug Informationen, um zu verstehen, was los ist.
Mundi
4
Interessanterweise musste ich entfernen @objc(MyClass)
Santa Claus
1
@ Mundi, vielleicht möchten Sie Ihre Antwort erneut aktualisieren. Siehe Khunshans Antwort-Update.
Suragch
75

SWIFT 2 / XCODE 7 Update:

Dieses Problem (siehe auch meinen Kommentar zu dieser Antwort vom 3. April) wurde in der Beta-Version von Swift 2 und XCode 7 von Apple behoben . Sie brauchen also jetzt eigentlich nicht in Swift, wie von Mundi beantwortet oder " " vor Ihrem Klassennamen verwendet. Es wird aufhören zu arbeiten. Also entfernen Sie diese, geben Sie einfach den Namen in die Datei ein und wählen Sie als Modul und Prost!@objc(myEntity)MyAppName.ClassCurrent Working Module

Aktuelles Arbeitsmodul auswählen

Aber für diejenigen, die @objc(myEntity)in Swift arbeiten (wie ich), können Sie stattdessen diese andere Lösung verwenden, die reibungslos funktioniert.

In der xcdatamodel richtigen Klasse in. Es sollte so aussehen:

Klasse einstellen

Bitte schön. Module.Classist das Muster für CoreData in Swift und XCode 6. Sie benötigen das gleiche Verfahren auch, wenn Sie die Klasse " Benutzerdefinierte Richtlinien" in Modellrichtlinien oder anderen CoreData-Elementen verwenden. Ein Hinweis: Im Bild sollten Name und Klasse Car und MyAppName.Car sein (oder wie auch immer der Name Ihrer Entität lautet). Hier Userist ein Tippfehler.

Khunshan
quelle
Das Problem bei dieser Lösung besteht darin, dass automatisch generierte Entitätsklassen nicht mehr ordnungsgemäß funktionieren (es wird nur eine Klasse mit dem Modulnamen generiert). Siehe: NSManagedObject-Unterklasse erstellen, die nicht ordnungsgemäß generiert wird .
Milos
Sie müssen die Lösung nach dem Generieren von NSManagedObject-Entitätsklassen anwenden. Wahrscheinlich muss ein xcode 6.xx-Fehler behoben werden.
Khunshan
2
Ja, dies wird zweifellos gelöst. Automatisch generierte Klassen sollten bereits mit @objc (<im Entitätsinspektor eingegebener Klassenname>) geschmückt sein. Andernfalls macht Apple dies zunächst unnötig.
Milos
2
Für Leute, die das noch lesen. Die Verwendung von ' MyAppName.Car ' hat bei mir nicht funktioniert, es hat funktioniert, als ich den ' MyAppName ' entfernt habe. Teil. Also nur Carfür beide Felder hat es den Trick gemacht.
Gideon
1
du Champ !!!! let person = NSEntityDescription.insertNewObject (forEntityName: "Person", in: context) as! Person
Abhimanyu Rathore
36

Bei Verwendung von Xcode 7 und rein Swift musste ich tatsächlich aus meiner automatisch generierten Unterklasse (generiert aus > ) entfernen .@objc(MyClass)NSManagedObjectEditorCreate NSManagedObject Subclass...

Weihnachtsmann
quelle
4
Wow, danke, dass du diese Antwort gepostet hast. Ich wollte gerade meinen Kopf gegen die Wand schlagen.
Zia
Gleiches Problem hier - Fehler eingereicht.
MirekE
Hat auch für mich gearbeitet. Musste es entfernen. Bizarr.
Kent
Nach meinen Experimenten sieht es wie ein falsches Positiv aus.
Mundi
Ich musste es entfernen und das aktuelle Produktmodul einstellen, nur dann funktionierte es
Oleg Sherman
13

In Xcode 7 Beta 2 (und ich glaube 1) wird in der Modellkonfiguration ein neues verwaltetes Objekt vom Typ Fileauf das Modul gesetzt Current Product Moduleund die Klasse des Objekts in der Konfiguration als angezeigt .File.

Modul des verwalteten Objekttyps in Xcode 7 auf "Aktuelles Produktmodul" gesetzt

Das Löschen der Moduleinstellung, damit sie leer ist, oder das Entfernen des Punkts, damit der Klassenname in der Konfiguration nur Fileäquivalente Aktionen sind, da jede die andere Änderung verursacht. Durch Speichern dieser Konfiguration wird der beschriebene Fehler behoben.

Das Modul des verwalteten Objekts ist in Xcode 7 leer

Duncan Babbage
quelle
9

In Xcode 6.1.1 müssen Sie das Attribut @objc nicht hinzufügen, da die Basisentität eine Teilmenge einer objc-Klasse (NSManagedObject) ist (siehe Swift- Typkompatibilität. In CoreData ist der vollständige Name der Module.Class erforderlich. Beachten Sie das Modul Der Name wird unter Build-Einstellungen -> Verpackung -> Name des Produktmoduls festgelegt. Standardmäßig ist dies auf $ (PRODUCT_NAME: c99extidentifier) ​​festgelegt, der der Name des Ziels ist .

Jim Malak
quelle
Ja! Dies ist die moderne Antwort (xcode 6.3.2). Die Verwendung des richtigen Bundle-Namens ist der Schlüssel. In meinem Fall war es umgewandelt my-productin my_product, und das machte den Unterschied zu Core Data.
Einfach
5

Mit xCode 7 und Swift 2.0 müssen Sie @objc (NameOfClass) nicht hinzufügen. Ändern Sie einfach die Entitätseinstellungen auf der Registerkarte "Show the Data Model Inspector" wie unten -

Name - "Name Ihrer Entität"

Klasse - "Ihr Entitätsname"

Modul - "Aktuelles Produktmodul"

Geben Sie hier die Bildbeschreibung ein

Der Code für die Entitätsklassendatei lautet wie folgt (in meinem Code Entität ist Familie) -

import UIKit
import CoreData

class Family: NSManagedObject {

   @NSManaged var member : AnyObject
}

Dieses Beispiel funktioniert in meiner App mit xCode 7.0 + swift 2.0 einwandfrei

Himanshu Mahajan
quelle
3

Vergessen Sie nicht, durch PRODUCT_MODULE_NAMEden Namen Ihres Produktmoduls zu ersetzen .

Wenn eine neue Entität erstellt wird, müssen Sie den Datenmodellinspektor (letzte Registerkarte) aufrufen und durch PRODUCT_MODULE_NAMEIhren Modulnamen ersetzen. class not foundAndernfalls tritt beim Erstellen des persistenten Geschäftskoordinators ein Fehler auf.

Kof
quelle
2

Sie müssen auch (zumindest mit Xcode 6.3.2) Module.Class verwenden, wenn Sie Ihre Besetzung durchführen, zum Beispiel: Angenommen, Ihr Modul (dh Produktname) ist Food und Ihre Klasse ist Fruit

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

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

Rekapitulieren:

  • Geben Sie den Modulnamen an, wenn Sie eine Entität im Datenmodell-Editor definieren (Name: Obst, Klasse: Lebensmittel.Frucht).
  • Wenn Sie auf die Entität im Code (ieSWIFT) zugreifen, wandeln Sie sie mit Module.class (z. B. Food.Fruit) um.
Wizkid
quelle
Vielen Dank, der zweite Punkt ist sehr wichtig. Ich musste "Module.Class" beim Casting verwenden.
Zoyt
1

Das Ändern des Namens der Entitätsklasse im Datenmodell-Editor, um der betreffenden Klasse zu entsprechen, und das Hinzufügen @objc(NameOfClass)zur Datei jedes NSManagedObject direkt über der Klassendeklaration löste dieses Problem für mich während des Komponententests.

user3269767
quelle
0

Was für mich funktioniert hat (Xcode 7.4, Swift), ist die Änderung des Klassennamens in <my actual class name>.<entity name> im Feld "Klasse" des Entitätsinspektors geändert.

Mein Initiator der Unterklasse "Verwaltetes Objekt" sieht folgendermaßen aus:

    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
Kennzeichen
quelle
0

Für Xcode 11.5: Wenn die Codegen-Eigenschaft die Klassendefinition ist und Sie keinen Vorschlag für die Entität erhalten, die Sie in xcdatamodel erstellt haben. Versuchen Sie, Xcode zu beenden und Ihr Projekt erneut zu öffnen. Für mich geht das. Diese Antwort ist nur, wenn Sie keine Vorschläge erhalten, aber wenn Ihre Datei nicht generiert wird, versuchen Sie eine der obigen Antworten.

Gulshan Kumar
quelle