Ich habe kürzlich mein iOS-App-Projekt auf iOS 10 aktualisiert. Jetzt versuche ich, das Kerndatenmodell meiner App zu ändern, aber die neuen Unterklassen von NSManagedObject, die Xcode generiert, sind defekt. Ich habe auch versucht, die Unterklassen manuell zu reparieren, aber das funktioniert nicht.
Die minimale Toolversion für das Core Data Model ist auf Xcode 7.0 und die Code-Generierungssprache auf Swift gesetzt.
Dies ist der Code, den Xcode generiert:
import Foundation
import CoreData
import
extension Group {
@nonobjc public class func fetchRequest() -> NSFetchRequest {
return NSFetchRequest(entityName: "Group");
}
@NSManaged public var name: String?
@NSManaged public var platform: NSNumber?
@NSManaged public var profiles: NSOrderedSet?
}
// MARK: Generated accessors for profiles
extension Group {
@objc(insertObject:inProfilesAtIndex:)
@NSManaged public func insertIntoProfiles(_ value: SavedProfile, at idx: Int)
@objc(removeObjectFromProfilesAtIndex:)
@NSManaged public func removeFromProfiles(at idx: Int)
@objc(insertProfiles:atIndexes:)
@NSManaged public func insertIntoProfiles(_ values: [SavedProfile], at indexes: NSIndexSet)
@objc(removeProfilesAtIndexes:)
@NSManaged public func removeFromProfiles(at indexes: NSIndexSet)
@objc(replaceObjectInProfilesAtIndex:withObject:)
@NSManaged public func replaceProfiles(at idx: Int, with value: SavedProfile)
@objc(replaceProfilesAtIndexes:withProfiles:)
@NSManaged public func replaceProfiles(at indexes: NSIndexSet, with values: [SavedProfile])
@objc(addProfilesObject:)
@NSManaged public func addToProfiles(_ value: SavedProfile)
@objc(removeProfilesObject:)
@NSManaged public func removeFromProfiles(_ value: SavedProfile)
@objc(addProfiles:)
@NSManaged public func addToProfiles(_ values: NSOrderedSet)
@objc(removeProfiles:)
@NSManaged public func removeFromProfiles(_ values: NSOrderedSet)
}
Bearbeiten: Dies sind die spezifischen Fehler, die Xcode gibt:
1. Group+CoreDataProperties.Swift:13:1: Expected identifier in import declaration (the empty import)
2. Group+CoreDataProperties.Swift:13:11: 'Group' is ambiguous for type lookup in this context
3. Group+CoreDataProperties.Swift:15:16: Cannot specialize non-generic type 'NSFetchRequest'
4. Group+CoreDataProperties.Swift:26:11: 'Group' is ambiguous for type lookup in this context
4. Group+CoreDataProperties.Swift:43:82: 'SavedProfile' is ambiguous for type lookup in this context
Ich habe endlich meine zur Arbeit gebracht. Hier ist was ich getan habe. (Flüge ist eine meiner Entitäten)
Ich setze das xcdatamodeld wie folgt ein
Und dann das Wesen als
Dann habe ich Editor -> Create NSManagedObject Subclass verwendet
Dadurch werden zwei Dateien für meine Flugeinheit erstellt
Flights + CoreDataProperties.Swift
Flüge + CoreDataClass.Swift
Ich habe Flights + CoreDataClass.Swift in Flights.Swift umbenannt
Flights.Swift ist nur
import Foundation
import CoreData
@objc(Flights)
public class Flights: NSManagedObject {
}
Flights + CoreDataProperties.Swift ist
import Foundation
import CoreData
extension Flights {
@nonobjc public class func fetchRequest() -> NSFetchRequest<Flights> {
return NSFetchRequest<Flights>(entityName: "Flights");
}
@NSManaged public var ...
}
Das scheint für mich zu funktionieren. Ich konnte Codegen nicht dazu bringen, auf andere Weise zu arbeiten, obwohl ich viele der Vorschläge ausprobierte.
Auch das hat mir eine Weile den Kopf gekratzt und ich füge es als Assist hinzu. Vergessen Sie nicht, dass Sie mit der neuen Generics-Version von FetchRequest dies tun können
let fetchRequest: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest(entityName: "Flights")
Ich glaube, der Grund, warum Sie nach dem Generieren der NSManagedObject-Unterklassendateien auf diese Fehler gestoßen sind, hängt möglicherweise mit der Codegen-Option zusammen, die zum Zeitpunkt der Änderung des Datenmodells ausgewählt wurde.
Ich denke nicht, dass das ein Fehler ist. Zumindest nicht in Xcode 8.1 (8B62).
Ich bin auf ein ähnliches Problem gestoßen und habe dieses Problem behoben, indem ich die Codegen-Option auf "Manual/None" geändert habe und die Option "Module" als "Global Namespace" belassen habe. Ich habe dann meine NSManagedObject-Unterklassendateien generiert. Abhängig von Ihrer Situation müssen Sie jedoch möglicherweise nicht einmal die Unterklassen NSManagedObject generieren.
Nachfolgend finden Sie weitere Details zur Entität Codegen-Optionen basierend auf meiner Überprüfung der Apple-Dokumentation, dem Apple-Entwicklerforum und dem Testen mit meinem eigenen Projekt.
Option 1: "Klassendefinition"
Stellen Sie sich dies als "Plug and Play" -Option vor
Verwenden Sie den Modelleditor zum Erstellen der Entitäten und zugehörigen Attribute .__, die Core Data verwalten soll.
Verwenden Sie nicht den NSMangagedObject-Unterklassengenerator. Die erforderlichen -Dateien werden von Xcode automatisch für Sie generiert (jedoch nicht in Ihrem Projektnavigator ).
Wenn Sie die NSManagedObject-Dateien generieren, teilt Apple Ihnen mit, dass diese Dateien nicht in den Header-Kommentaren der genannten .__-Dateien bearbeitet werden sollten. Wenn Sie diese Dateien bearbeiten müssen, ist dies ein gutes Zeichen, dass Sie eine andere Codegen-Option verwenden müssen.
Behalten Sie die Standardoptionen der Klasse für Ihre Entität bei (Module = Global Namespace und Codegen = Klassendefinition).
Wenn Sie Methoden des NSManagedObject überschreiben müssen, können Sie eine Erweiterung unter Verwendung des Namens unter der Option Class erstellen.
// Optional extension in Entity.Swift
extension Entity {
// Override NSManagedObject methods
}
Optionen 2: "Manuell/Keine"
Ähnlich wie Option 1, außer dass Sie die NSManagedObject-Unterklassendateien anzeigen und bearbeiten können.
Verwenden Sie den Modelleditor zum Erstellen der Entitäten und zugehörigen Attribute .__, die Core Data verwalten soll.
Setzen Sie vor der Verwendung des NSManagedObject-Unterklassengenerators die Option Codgen Auf "Manual/None" für die Entität. Die Moduloption sollteGlobal Namespace sein.
Nachdem Sie ein Attribut hinzugefügt/entfernt/aktualisiert haben, haben Sie zwei Möglichkeiten: (1) Aktualisieren Sie manuell die NSManagedObject-Dateien, die für Sie generiert wurden ODER (2) Verwenden Sie den NSManagedObject-Unterklassengenerator erneut (dies wird Aktualisieren Sie nur die Entity + CoreDataProperties.Swift-Datei).
Wenn Sie und Methoden von NSManagedObject überschreiben müssen, können Sie eine Erweiterung erstellen. Die Erweiterung sollte in der Entity + CoreDataClass.Swift-Datei und nicht in der Entity + CoreDataProperties.Swift-Datei erstellt werden (diese Datei könnte aufgrund von Änderungen des Modell-Editors aktualisiert werden).
// Optional extension in Entity+CoreDataClass.Swift
extension Entity {
// Override NSManagedObject methods
}
Option 3: "Kategorie/Erweiterung"
Verwenden Sie diese Option, wenn Sie über benutzerdefinierte Eigenschaften verfügen, die nicht von Core Data verwaltet werden müssen.
Verwenden Sie den Modelleditor zum Erstellen der Entitäten und zugehörigen Attribute .__, die Core Data verwalten soll.
Stellen Sie sicher, dass die Option Modul auf Aktuelles Produktmodul und die Option Codegen auf "Kategorie/Erweiterung" gesetzt ist.
Erstellen Sie Ihre eigene NSManagedObject-Unterklasse mit den Eigenschaften, die Sie selbst verwalten.
Verwenden Sie nicht den NSMangagedObject-Unterklassengenerator. Die erforderlichen -Dateien werden von Xcode automatisch für Sie generiert (jedoch nicht in Ihrem Projektnavigator ).
// Subclass NSManagedObject in Entity.Swift
class Entity: NSManagedObject {
// Self managed properties
}
// Optional extension in Entity.Swift
extension Entity {
// Override NSManagedObject methods
}
Sie können diese Schritte ausprobieren
Ist das Arbeit? Wenn nicht
Stellen Sie sicher, dass Sie alle Klassen nicht mit Entities denselben Namen haben. Sie finden diese Klassen in Build Phases -> Compile Sources . Benennen Sie die Klasse oder Entitäten um, wenn sie dupliziert werden
Oder
Sie können diesen Befehl in Ihrem Projektordner ausführen, um weitere Fehlerinformationen zu erhalten
xcodebuild -verbose
Ich habe diese Nachricht erhalten, wenn ich dieses Problem habe
doppeltes Symbol _OBJC_CLASS _ $ _ RandomList in:
xxxx/RandomList.o
xxxx/RandomList + CoreDataClass.o
RandomList.h und RandomList + CoreDataClass.h haben beim Kompilieren dasselbe Symbol
Ich denke, dass Xcode Sie nicht gewarnt hat, aber der Compiler wird einen Fehler auslösen
Hoffe, das wird dir helfen
Löschen Sie die dritte import
-Anweisung, da sie leer ist.
Hinweis: Ich weiß nicht, warum das so ist, aber ich denke, es ist ein Fehler in Xcode 8. Löschen Sie ihn einfach und es funktioniert gut.
Ich hatte gerade ein Problem, als ich in der Vorlage "Core Data" eine Personenentität in meinem Modell hinzugefügt habe. Dann generierte ich die NSManagedObject-Unterklasse dafür und es wird nicht kompiliert, was einen Linker-Fehler ergibt. Es stellt sich heraus, dass ich die Codegen-Option in Manuell/Keine ändern muss, damit sie funktioniert (siehe rechten unteren Teil des Bildes) .
Ich denke, dass es ein xcode Problem ist, in dem xcode falsche Syntax für Kerndatenkategorieklasse erzeugt. Ich erstelle ein nsmanageobjectsubclass
für eine Entität AgentDetails
Hier erzeugt xcode eine falsche Codestruktur in AgentDetails+CoreDataClass.h
Und AgentDetails+CoreDataClass.m
. Diese haben eine Codestruktur wie:
Und
Es liegt also ein doppeltes Schnittstellenproblem vor, da AgentDetails.h
Dieselbe Schnittstelle hat.
Um dies zu beheben, müssen Sie den Code in AgentDetails+CoreDataClass.h
Ändern.
und AgentDetails+CoreDataClass.m
wie folgt:
Wählen Sie im Data Model Inspector unter 'Module' die Option Current Product Module und unter 'Codegen' die Option Manual/None. (Dadurch können Sie Unterklassendateien bearbeiten und CoreDataProperties.Swift neu generieren, wenn Sie Ihre Attribute unter derselben Entität ändern.)
Sie können dann im Menü "Editor" die Option "NSManagedObjectSubclass" auswählen. Xcode erstellt 2 Dateien für Sie: YourEntity + CoreDataClass.Swift und YourEntity + CoreDataProperties.Swift. Wenn Sie nicht über den neuesten Xcode (8.2.1) verfügen, werden optionale/nicht optionale Eigenschaften, die Sie in Model Inspector festgelegt haben, nicht richtig angezeigt. Sie können in der YourEntity + CoreDataProperties.Swift-Datei bearbeiten.
Wenn Sie die Unterklasse NSManagedObject selbst hinzufügen, vergessen Sie nicht, den folgenden Schritt zu befolgen: Gehen Sie zu '.xcdatamodeld' -> Wählen Sie die Entität aus.
Das hat bei mir funktioniert.
Xcode 8.1 scheint die Model Class intern zu generieren. Löschen Sie einfach die zwei erstellten Klassen und Sie können die Entitäten in Ihrem Code weiterhin verwenden.
Hier ist die Fehlermeldung, die ich erhalten habe
<unknown>:0: error: filename "Recipe+CoreDataProperties.Swift" used twice: '/Users/Rick/Desktop/Devslop/Rick Recipe/Recipe+CoreDataProperties.Swift' and '/Users/Rick/Library/Developer/Xcode/DerivedData/Rick_Recipe-cctgjudvqobxlwetbcwmzrgxigwg/Build/Intermediates/Rick Recipe.build/Debug-iphonesimulator/Rick Recipe.build/DerivedSources/CoreDataGenerated/Rick_Recipe/Recipe+CoreDataProperties.Swift'
<unknown>:0: note: filenames are used to distinguish private declarations with the same name
Command /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swiftc failed with exit code 1
Ich habe es wie im folgenden Beispiel gelöst
Erstelle CurrentcyPair.xcdatamodeld
wählen Sie CurrentcyPair.xcdatamodeld und wählen Sie Default -> Entity (CurrencyPair), benennen Sie die Klasse um in (.ManagedCurrencyPair)
Wählen Sie Entität und öffnen Sie den Inspektor. Setze Code Gen am Datenmodell als Manual/None
Ich habe diese Post von David Atkinson gefunden, die irgendwie hilfreich ist ... Wenn ich den Code so generiere, wie David es beschrieben hat. Ich bekomme nur den Code mit einigen Syntaxfehlern und wenn ich die Fehler behebe, funktioniert alles wie zuvor. Es gibt keine fehlenden Dateien, die mit '.' Beginnen. nicht mehr.
Die Syntaxfehler, die ich korrigieren muss, sind - der unnötige Import - und einige öffentliche Eigenschaften, die in meinem Code nicht öffentlich sein sollen
Ich gebe mein Salzkorn in Anbetracht dessen, dass ich viele Antworten sehen kann, die das Problem lösen, aber fehlt der wahre Grund dafür, was hier wirklich passiert.
Ich bin über dieses Thema gestolpert und habe durch eine kurze Recherche herausgefunden, dass:
Bis zu Xcode 7 bestand das Standardverhalten für eine Core Data-Entität darin, dass der Entwickler die Änderungen der entsprechenden NSManagedObject-Unterklassen manuell erstellen und verwalten musste. (Dies kann und kann durch Verwendung des Editormenüs erreicht werden, indem die Option "NSManagedObject-Unterklasse erstellen ..." ausgewählt wird).
Ab Xcode 8 hat Apple im Data Model Inspector eine neue Einstellung mit dem Namen Codegen hinzugefügt, um die Unterklassen von NSManagedObject zu verwalten und zu verwalten. Der Standardwert für diese Einstellung ist "Class Definition" (Klassendefinition), der Xcode anweist, die Unterklassen von NSManagedObject basierend auf unseren definierten Entitäten in der Kompilierzeit zu generieren und sie in den Ordner für abgeleitete Daten abzulegen.
Da unsere NSManagedObject-Unterklassen innerhalb des Projekts + die von Xcode automatisch generierten Subklassen sind, führt dies zu dem eigentlichen Grund für den Zeitfehler "Mehrere Befehle erzeugen ...", da jetzt Modelle für verwaltete Objekte dupliziert wurden.
Die Lösung ist, entweder das eine oder das andere zu verwenden, nicht beides! Ich persönlich bevorzuge es, meine verwalteten Objektmodelle innerhalb des Projekts zu haben, daher habe ich diese "Codegen" -Einstellung in "Manuell/Keine" geändert. Wenn Sie den Modellen keine Logik hinzufügen, können Sie sich entscheiden, indem Sie die verwalteten Objektmodelle Ihres Projekts entfernen und Xcode seine Aufgabe basierend auf dem Wert "Class Definition" für die erwähnte Einstellung erledigen lassen. Dies ist der richtige Weg, um mit diesem Problem umzugehen.
Hier finden Sie einen großartigen Artikel, der all dies ausführlich erklärt:
https://medium.com/@kahseng.lee123/core-data-codegen-explained-462c30341041
Ich verwende den neuesten Build für Xcode 8.1 Beta (8T47).
Gemäß dem Fehlerprotokoll (siehe unten) werden zwei Kopien der automatisch generierten Dateien erstellt. Eine Kopie wird in Ihrem Xcode-Projektordner abgelegt (in der linken Symbolleiste von Xcode in Ihrem Verzeichnis sichtbar) und eine zweite Kopie wird in Ihrem DerivedData-Ordner für Ihr Projekt erstellt:
/Users/<your name>/Library/Developer/Xcode/DerivedData/<your app>-axhtnodotznxnrenefflktnxfeal/Build/Intermediates/<your app>.build/Debug-iphonesimulator/<your app>.build/DerivedSources/CoreDataGenerated/<your app>/<class name>+CoreDataProperties.Swift
/Users/<your name>/Library/Developer/Xcode/DerivedData/<your app>-axhtnodotznxnrenefflktnxfeal/Build/Intermediates/<your app>.build/Debug-iphonesimulator/<your app>.build/DerivedSources/CoreDataGenerated/<your app>/<class name>+CoreDataClass.Swift
Das Löschen der Kopien in Ihrem Xcode-Projektverzeichnis behebt alle Probleme, ist jedoch sinnlos, da Sie diese Dateien nicht mehr bearbeiten können.
Ich würde nicht sagen, dass dies eine Lösung ist, sondern nur eine halbherzige Methode, um das Projekt zu bauen. Hoffentlich wird dieser Fehler bald behoben.
Für mich habe ich CocoaTouch-Klassen erstellt, indem Sie manuell NSManagedObject
subclassing. Ich habe das Modul als Current Product Module und Codegen als Kategorie/Erweiterung eingestellt und es funktioniert gut.
In meinem speziellen Fall hatte ich CoreData zu einem vorhandenen Projekt hinzugefügt, das bereits eine Model-Klasse mit demselben Namen wie meine Entität hatte. Durch das Löschen der alten Model-Klasse wurde das Problem behoben, da der Typ mit der neuen CoreData-Entity-Klasse kollidierte.