J'ai récemment mis à jour mon projet d'application iOS avec iOS 10. J'essaie maintenant de modifier le modèle de données principal de mon application, mais les nouvelles sous-classes NSManagedObject générées par Xcode sont endommagées. J'ai aussi essayé de corriger le manuel des sous-classes mais cela ne fonctionne pas.
La version minimale des outils pour Core Data Model est définie sur Xcode 7.0 et le langage de génération de code est défini sur Swift.
C'est le code généré par Xcode:
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)
}
Edit: Voici les erreurs spécifiques que Xcode donne:
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
J'ai finalement eu le mien au travail. Voici ce que j'ai fait. (Vols est l'une de mes entités)
J'ai installé le xcdatamodeld comme suit
Et puis l'entité en tant que
Ensuite j'ai utilisé Editor -> Create NSManagedObject Subclass
Cela crée deux fichiers pour mon entité de vols
Vols + CoreDataProperties.Swift
Vols + CoreDataClass.Swift
J'ai renommé Flights + CoreDataClass.Swift en Flights.Swift
Flights.Swift est juste
import Foundation
import CoreData
@objc(Flights)
public class Flights: NSManagedObject {
}
Flights + CoreDataProperties.Swift est
import Foundation
import CoreData
extension Flights {
@nonobjc public class func fetchRequest() -> NSFetchRequest<Flights> {
return NSFetchRequest<Flights>(entityName: "Flights");
}
@NSManaged public var ...
}
Cela semble fonctionner pour moi. Je ne pouvais pas obtenir que Codegen fonctionne de toute autre manière, même si j’ai essayé la plupart des suggestions proposées.
De plus, cela me faisait me gratter la tête pendant un moment et je l’ajoute comme aide. N'oubliez pas qu'avec la nouvelle version générique de FetchRequest, vous pouvez le faire.
let fetchRequest: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest(entityName: "Flights")
Je pense que la raison pour laquelle vous avez rencontré ces erreurs après avoir généré les fichiers de sous-classe NSManagedObject peut être liée à l'option Codegen sélectionnée au moment de la modification de votre modèle de données.
Je ne pense pas que ce soit un bug. Du moins pas dans Xcode 8.1 (8B62).
J'ai rencontré un problème similaire et l'ai corrigé en modifiant l'option Codegen en "Manuel/Aucun" et en laissant l'option Module en "Espace de noms global". J'ai ensuite généré mes fichiers de sous-classe NSManagedObject. Toutefois, selon votre situation, il se peut que vous n’ayez même pas besoin de générer les sous-classes NSManagedObject.
Vous trouverez ci-dessous des informations plus détaillées sur les options de l'entité Codegen basées sur mon examen de la documentation Apple, le forum du développeur Apple et les tests réalisés avec mon propre projet.
Option 1: "Définition de classe"
Pensez à cela comme à l'option "plug and play"
Utilisez l'éditeur de modèle pour créer les entités et les attributs associés .__ que vous souhaitez que Core Data gère.
N'utilisez pas le générateur de sous-classe NSMangagedObject. Les fichiers Requis sont générés automatiquement pour vous par Xcode (cependant, ils ne s'affichent pas dans le navigateur de projet).
Si vous générez les fichiers NSManagedObject, Apple vous indique que Ces fichiers ne doivent pas être modifiés dans les commentaires d’en-tête de ces fichiers Si vous avez besoin d'éditer ces fichiers, cela signifie que vous devez utiliser une autre option Codegen.
Laissez les options de classe par défaut pour votre entité (Module = Global Namespace et Codegen = Définition de classe)
Si vous devez remplacer les méthodes de NSManagedObject, vous pouvez créer une extension à l’aide de l’option Nom sous la classe.
// Optional extension in Entity.Swift
extension Entity {
// Override NSManagedObject methods
}
Option 2: "Manuel/Aucun"
Identique à l'option 1, sauf que vous pouvez voir et éditer les fichiers de sous-classe NSManagedObject.
Utilisez l'éditeur de modèle pour créer les entités et les attributs associés .__ que vous souhaitez que Core Data gère.
Avant d'utiliser le générateur de sous-classe NSManagedObject, définissez l'option Codgen Sur "Manuel/Aucun" pour l'entité. L'option Module devrait êtreGlobal Namespace.
Après avoir ajouté/supprimé/mis à jour un attribut, vous avez le choix: (1) Mettez à jour manuellement les fichiers NSManagedObject générés pour vous OU (2) Utilisez à nouveau le générateur de sous-classe NSManagedObject (cela permettra. mettre à jour uniquement le fichier Entity + CoreDataProperties.Swift).
De nouveau, si vous devez remplacer des méthodes à partir de NSManagedObject, vous pouvez créer une extension. L'extension doit être créée dans le fichier Entity + CoreDataClass.Swift et non dans le fichier Entity + CoreDataProperties.Swift (ce fichier peut être mis à jour en raison de la modification de l'éditeur de modèle).
// Optional extension in Entity+CoreDataClass.Swift
extension Entity {
// Override NSManagedObject methods
}
Option 3: "Catégorie/Extension"
Utilisez cette option si vous avez des propriétés personnalisées qu'il n'est pas nécessaire de gérer Par Core Data.
Utilisez l'éditeur de modèle pour créer les entités et les attributs associés .__ que vous souhaitez que Core Data gère.
Assurez-vous que l'option Module est définie sur Module produit actuel et que l'option Codegen est définie sur "Catégorie/Extension".
Créez votre propre sous-classe NSManagedObject avec les propriétés que vous allez gérer vous-même.
N'utilisez pas le générateur de sous-classe NSMangagedObject. Les fichiers Requis sont générés automatiquement pour vous par Xcode (cependant, ils ne s'affichent pas dans le navigateur de projet).
// Subclass NSManagedObject in Entity.Swift
class Entity: NSManagedObject {
// Self managed properties
}
// Optional extension in Entity.Swift
extension Entity {
// Override NSManagedObject methods
}
Vous pouvez essayer ces étapes
Est-ce que le travail? Si non
Assurez-vous que tous class n'a pas le même nom avec Entities . Vous pouvez trouver ces classes dans Build Phases -> Compile Sources . Renommez la classe ou les entités si elles sont dupliquées
Ou
Vous pouvez exécuter cette commande dans votre dossier de projet pour obtenir plus d’informations sur les erreurs.
xcodebuild -verbose
J'ai eu ce message quand j'ai ce problème
symbole en double _OBJC_CLASS _ $ _ RandomList dans:
xxxx/RandomList.o
xxxx/RandomList + CoreDataClass.o
RandomList.h et RandomList + CoreDataClass.h ont le même symbole lors de la compilation
Je pense que pourquoi Xcode ne vous a pas prévenu, mais le compilateur jettera une erreur
J'espère que ceci vous aidera
Supprimez la 3ème instruction import
car elle est vide.
Remarque: je ne sais pas pourquoi cela se produit, mais je suppose que c'est un bogue dans Xcode 8. Supprimez-le et tout ira bien.
Je viens d'avoir un problème où je viens d'ajouter une entité Personne dans mon modèle au modèle Données de base. Puis généré la sous-classe NSManagedObject pour cela et il ne compilera pas, me donnant une erreur de l'éditeur de liens. Il s'avère que je suis censé changer l'option Codegen en Manuel/Aucun pour que cela fonctionne (voir la partie inférieure droite de l'image) .
Je pense que c'est un problème de xcode, où xcode génère une syntaxe incorrecte pour la classe de catégorie de données principale . Je crée un nsmanageobjectsubclass
pour une entité AgentDetails
Ici, xcode crée une structure de code incorrecte dans AgentDetails+CoreDataClass.h
et AgentDetails+CoreDataClass.m
. Ceux-ci ont une structure de code comme:
Et
Donc, il y a un problème d'interface en double puisque AgentDetails.h
a la même interface.
Maintenant, pour résoudre ce problème, vous devez changer le code dans AgentDetails+CoreDataClass.h
et AgentDetails+CoreDataClass.m
comme ceci:
Dans Data Model Inspector, sélectionnez Current Product Module sous 'Module' et Manual/None sous 'Codegen'. (Cela vous permet d'éditer des fichiers de sous-classe et de régénérer CoreDataProperties.Swift lorsque vous modifiez vos attributs sous la même entité.)
Vous pouvez ensuite choisir Create NSManagedObjectSubclass dans le menu Editor. Xcode créera 2 fichiers pour vous YourEntity + CoreDataClass.Swift et YourEntity + CoreDataProperties.Swift. Notez que si vous ne possédez pas le dernier Xcode (8.2.1), les propriétés facultatives/non optionnelles que vous avez définies dans votre inspecteur de modèle ne seront pas affichées correctement. Vous pouvez modifier le fichier YourEntity + CoreDataProperties.Swift.
De même, si vous ajoutez vous-même une sous-classe NSManagedObject, n'oubliez pas de suivre l'étape suivante:
Cela a fonctionné pour moi.
Xcode 8.1 semble générer la classe de modèle en interne. Supprimez simplement les 2 classes créées et vous pourrez toujours utiliser les entités de votre code.
Voici le message d'erreur que je recevais
<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
Je l'ai résolu comme un exemple donné ci-dessous
Créer CurrentcyPair.xcdatamodeld
sélectionnez CurrentcyPair.xcdatamodeld et sélectionnez Par défaut -> Entity (CurrencyPair), renommez la classe en (.ManagedCurrencyPair)
Sélectionnez Entity et ouvrez l'inspecteur. Définissez le code gen dans le modèle de données sur Manuel/Aucun
J'ai trouvé ceci Message de David Atkinson qui est utile d'une certaine manière… .. Si je génère le code de la manière décrite par David. Je viens d'obtenir le code avec des erreurs de syntaxe et si je corrige les erreurs, tout fonctionne comme avant. Il ne manque aucun fichier commençant par '.' pas plus.
Les erreurs de syntaxe que je dois corriger sont - l’importation inutile - et certaines propriétés publiques qui ne sont pas destinées à être publiques dans mon code
Je mets mon grain de sel étant donné que je peux voir beaucoup de réponses qui résolvent le problème mais manquent la vraie raison derrière ce qui se passe vraiment ici.
Je suis tombé sur le même problème et en faisant une recherche rapide, j'ai pu constater que:
Avant Xcode 7, le comportement par défaut d'une entité Core Data était que le développeur devait créer et gérer manuellement les modifications des sous-classes NSManagedObject correspondantes. (Ceci peut et peut encore être accompli en utilisant le menu de l’éditeur en sélectionnant l’option "Créer une sous-classe NSManagedObject ..").
À partir de Xcode 8, Apple a intégré un nouveau paramètre dans l'inspecteur de modèle de données nommé Codegen pour gérer et gérer les sous-classes NSManagedObject. La valeur par défaut de ce paramètre est "Définition de classe", qui indique à Xcode de générer les sous-classes NSManagedObject en fonction de nos entités définies au moment de la compilation et de les placer dans le dossier de données dérivé.
Avoir nos sous-classes NSManagedObject dans le projet + celles générées automatiquement par Xcode nous amène à la véritable raison derrière l'erreur de compilation "Plusieurs commandes produisent ..." car nous avons maintenant des modèles d'objets gérés dupliqués !!!
La solution consiste alors à utiliser l'un ou l'autre, pas les deux! Personnellement, je préfère avoir mes modèles d'objet géré dans le projet et j'ai donc changé le paramètre "Codegen" en "Manuel/Aucun". Si vous n’ajoutez pas de logique aux modèles, je parie que vous pouvez choisir de supprimer les modèles d’objet géré de votre projet et de laisser Xcode agir en fonction de la valeur "Définition de la classe" du paramètre mentionné. C’est la bonne façon de régler ce problème.
Vous pouvez trouver un excellent article expliquant tout cela en détail ici:
https://medium.com/@kahseng.lee123/core-data-codegen-explained-462c30341041
J'utilise la dernière version bêta de Xcode 8.1 (8T47).
Selon le journal des erreurs (voir ci-dessous), deux copies des fichiers générés automatiquement sont créées. Une copie est placée dans votre dossier de projet Xcode (celle visible dans votre répertoire dans la barre d’outils de gauche de Xcode), et une seconde copie est créée dans votre dossier DerivedData pour votre projet:
/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
La suppression des copies dans le répertoire de votre projet Xcode résoudra tous les problèmes, mais ne sert à rien, vous ne pouvez plus modifier ces fichiers ...
Je ne dirais pas que c'est une solution, mais plutôt une façon à moitié assommée de faire en sorte que le projet se construise. Espérons que ce bug sera bientôt résolu.
Pour ma part, j'ai créé les classes CocoaTouch en sous-classant manuellement NSManagedObject
. Je règle le module en tant que module de produit actuel et Codegen en tant que catégorie/extension et cela fonctionne bien.
Dans mon cas particulier, j'avais ajouté CoreData à un projet existant comportant déjà une classe Model du même nom que mon entité. La suppression de l'ancienne classe Model a résolu le problème, car son type entrait en collision avec la nouvelle classe CoreData Entity.