Lisez cette réponse si le message d'erreur fait référence aux fichiers Core Data
Synopsis: Vous pouvez avoir à la fois des fichiers de classe d'objets gérés Core Data générés automatiquement et générés manuellement.
Cette réponse s'applique si la première ligne de l'erreur fait référence à un fichier Foo + CoreDataProperties.o ou Foo + CoreDataClass.o . Exemple:
error: Multiple commands produce '/Users/me/Library/Developer/Xcode/DerivedData/MyApp-uebslaqdwgldkjemijpdqmizgyzc/Build/Intermediates.noindex/ MyApp /Debug-iphonesimulator/ MyApp.build/Objects-normal/x86_64/Foo+CoreDataProperties.o':
1) Target ' MyApp ' (project ' MyApp ') has compile command for Swift source files
2) Target ' MyApp ' (project ' MyApp ') has compile command for Swift source files
La cause première peut être vue en développant la section Compile Swift Source Files du Build Transcript. Par exemple:
<unknown>:0: error: filename "Address+CoreDataClass.swift" used twice: '/Users/myUserName/Projects/Jnky/Foo+CoreDataProperties' and '/Users/jk/myUserName/Developer/Xcode/DerivedData/MyApp-uebslaqdwgldkjemijpdqmizgyzc/Build/Intermediates.noindex/MyApp.build/Debug/MyApp.build/DerivedSources/CoreDataGenerated/Jnky/Foo+CoreDataProperties.swift'
Le premier fichier mentionné il y a un fichier source dans votre répertoire de projet, que quelqu'un a généré en sélectionnant votre modèle de données dans le Navigateur du projet et en cliquant dans le menu Editeur > Créer une sous-classe d'objets gérés . Cette fonctionnalité a été ajoutée dans Xcode 7 ou plus.
Le deuxième fichier est un fichier du même nom mais qui est enterré dans Xcode DerivedData
. Ce fichier est généré automatiquement par Xcode lors de chaque génération si le .xcdatamodeld
fichier modèle de données ( ) est inclus dans la phase de génération des sources de compilation de la cible . Cette fonctionnalité a été ajoutée dans Xcode 9 ou plus. Zéro, un ou deux fichiers sont générés pour chaque entité / classe, selon le paramétrage du popup Codegen . Cette fenêtre contextuelle se trouve dans l' inspecteur de modèle de données lorsque vous sélectionnez une entité lors de la modification de votre modèle de données…
Les paramètres sont les suivants:
- Manuel / Aucun Aucun fichier n'est généré
- Catégorie / Extension Un fichier, Foo + CoreDataProperties.m ou .swift est généré, contenant une catégorie Objective-C ou une extension Swift.
- Définition de classe Ce même fichier de catégorie / extension est généré, et en outre un Foo + CoreDataClass.m ou .swift est généré, contenant la déclaration et la définition de classe.
Vous voyez donc que le problème se produit lorsqu'un développeur (comme moi) habitué à l'ancien Xcode commence un projet dans un Xcode plus récent. Nous pensons que nous devons utiliser l' élément de menu Créer une sous-classe d'objets gérés , ce que nous faisons, pour créer les fichiers que nous pouvons voir dans le navigateur de projet sans se rendre compte que nos paramètres dans la fenêtre contextuelle Codegen amènent Xcode à créer des fichiers en double, ce qu'Apple "intelligemment" ne s'affiche pas dans le Navigateur du projet, car ils ne font pas confiance aux développeurs pour lire et tenir compte du commentaire dans l'en-tête // Ce fichier a été généré automatiquement et ne doit pas être modifié.
Solution 1 - Utilisez l'ancienne méthode
Vous pouvez désactiver tous les Codegen automatiques pour un modèle de données avec un seul paramètre:
- Ouvrez les phases de construction de la cible du problème (dans Project Navigator , sélectionnez le projet, puis dans la liste des CIBLES qui apparaît, sélectionnez la cible du problème, puis l'onglet Build Phases ).
- Développez l' entrée Compiler les sources et recherchez le modèle de données du problème (
.xcdatamodeld
fichier).
- Supprimez-le de la liste de compilation
- Assurez-vous que le modèle de données est inclus dans la liste Copy Bundle Resources .
Solution 2 - Core Data Magic pour les débutants
Ici, vous vous lancez sur la nouvelle voie.
- Laissez votre modèle de données tel quel dans la compilation des sources .
- Dans chaque inspecteur d'entité de votre modèle de données, définissez Codegen sur Définition de classe .
- Dans le Navigateur du projet, supprimez et supprimez tous les fichiers Foo + CoreDataClass et renommez tous les fichiers Foo + CoreDataProperties.m ou .swift en quelque chose comme Foo + MyProperties .
- Dans chaque fichier Foo + MyProperties.m ou .swift , s'il existe des propriétés générées par Xcode, supprimez ces propriétés car elles se trouveront dans les fichiers cachés créés par Codegen .
Avec cette solution, vos définitions de classe sont générées automatiquement à partir du modèle de données sur chaque génération. Vous ne pouvez même pas les voir. C'est Core Data Magic , agréable et simple pour les débutants.
Solution 3 - Pour la plupart des applications du monde réel
Mais la solution 2 n'est pas bonne si vous voulez vraiment ajouter des propriétés non gérées. (Objective-C ne permet pas l'ajout de propriétés dans les catégories, et Swift ne permet pas l'ajout de propriétés stockées dans les extensions.) Ainsi, dans la plupart des applications du monde réel, vous voudrez probablement aller à mi-chemin entre les solutions 1 et 2…
- Laissez votre modèle de données dans la liste des sources de compilation
- Dans chaque inspecteur d'entité de votre modèle de données, définissez Codegen sur Catégorie / Extension .
- Dans le Navigateur du projet, supprimez et supprimez tous les fichiers Foo + CoreDataClass.m ou .swift et, pour réduire la confusion future, renommez tous les fichiers Foo + CoreDataProperties.m ou .swift en peut-être simplement Foo.m ou .swift .
- Assurez-vous que chaque fichier Foo.m ou .swift contient la définition de classe, à laquelle vous pouvez ajouter vos propres propriétés non gérées.
(Remerciements à la réponse de Positron. Ma réponse ici explique pourquoi la réponse de Positron (ma solution 1) fonctionne, et ajoute la solution 2 et la solution 3.)