wake-up-neo.com

Xcode 8 generiert beschädigte NSManagedObject-Unterklassen für iOS 10

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
61
Remco Beugels

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

 enter image description here

Und dann das Wesen als

 enter image description here

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")
104
Longmang

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 }

42
Ryan H.
  1. Um dieses Problem zu lösen, löschen Sie die abgeleiteten Daten der App.

  2. Ändern Sie dann Module in Current Product Module und nehmen Sie auch Änderungen in Codegen in Manual/None vor.

  3.  List item
39
akshay

Versuchen Sie, CodeGen einzustellen: Manual/None Module: Current Product Module

Es hat gut für mich funktioniert, als ich vor demselben Problem stand.

 enter image description here

17
Daniel Chepenko

Sie können diese Schritte ausprobieren

  1. Wählen Sie die Datei .xcdatamodeld im Xocde Project Navigator aus
  2. Stellen Sie im Data Modul Inspector sicher, dass Codegen : Manual/None
  3. Dann Edit -> NSManagedObject-Unterklasse erstellen
  4. Produkt reinigen und neu aufbauen

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

9
SamBundy

Wenn Sie eine ältere App haben und manuell verwaltete Objektklassen hinzufügen möchten

  1. Stellen Sie sicher, dass Ihr Kerndatenmodell codegen auf Manual/None gesetzt ist.
  2. Wählen Sie Ihre Kerndatenmodelldatei aus
  3. Erstellen Sie eine Unterklasse für verwaltete Objekte

 screenshot of editor

7
Neil Japhtha

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.

6
Lawrence413

Am Xcode 8.2.1 habe ich es so gemacht: (Danke für Daniel Chepenko)

 enter image description here

Aber Xcode 8.2.1 fügt ein dummes hinzu. in die generierten Dateien:

 enter image description here

Löschen Sie einfach das . und es wird richtig laufen.

5
Alpha Liu

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) .  enter image description here

4
ppalancica

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 AgentDetailsIt is creating the following classes

Hier erzeugt xcode eine falsche Codestruktur in AgentDetails+CoreDataClass.h Und AgentDetails+CoreDataClass.m. Diese haben eine Codestruktur wie:

enter image description here

Und

enter image description here

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.

enter image description here

und AgentDetails+CoreDataClass.m wie folgt:

enter image description here

3
souvickcse

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

 enter image description here

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. 

2
Ohmy

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.

1

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
1
user1988055

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

enter image description here

enter image description here

0
Wasim

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

0
tetanuss

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.

 Error Log

0
Mike

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.

0
mstntsnr

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.

0
jonbauer