J'essaie de travailler sur un projet mixte Swift et ObjectiveC sans succès.
Mon projet est composé de 6 cibles:
J'ai pu ajouter une classe Swift ayant une appartenance cible (App) et utilisant le code ObjectiveC transmis depuis le App-Bridging-Header.h Le paradigme "ObjectiveC into Swift code" fonctionne comme un charme.
Au lieu de cela, je lutte avec le paradigme "Swift into ObjectiveC code" . Dans le cas spécifique, je dois utiliser une nouvelle classe Swift dans un fichier ObjectiveC .m membre de quatre cibles.
Ce que j'ai fait jusqu'à présent est la suivante:
J'ai suivi le guide Mix and Match de Apple et beaucoup SO - fils de discussion comprenant celui-ci qui semble apparemment résoudre le même problème mais il ne fonctionne pas.
J'ai également vu ceci et ceci mais n'a pas fonctionné.
J'ai également essayé de supprimer les données dérivées et de nettoyer le projet dans son intégralité plusieurs fois sans succès.
EDIT 1: Plus de détails
Ceci est la déclaration de ma classe Swift importer RealmSwift
@objc class MyClass: Object {}
C’est le bout d’utilisation de la classe Swift dans ObjectiveC
MyClass *app = [[MyClass alloc] init];
Si j'évite d'utiliser #import ...- Swift.h, la construction échoue en indiquant que je me sers d'un identificateur non déclaré "MyClass" et que le son est bon.
Si j’utilise les fichiers #import ...- Swift.h, cela signifie que le module X ne peut pas trouver le module Y, etc.
EDIT 2: nom du module Swift
En examinant la propriété Swift_OBJC_INTERFACE_HEADER_NAME de chaque cible, j'ai constaté qu'elle est construite à l'aide de cette syntaxe $ (Swift_MODULE_NAME) -Swift.h dois-je modifier Swift_MODULE_NAME en MODULE_NAME?
EDIT 3: Importations
Voici l'ensemble des importations pour les en-têtes Swift dans le fichier .m ObjectiveC . J'utilise les noms de module spécifiés dans les propriétés relatives aux paramètres de construction. Notez que l’un a le caractère '_' car la cible de WatchKit Extension a un espace dans le nom de la cible.
#import "ProjectName_App-Swift.h"
#import "ProjectName_Core-Swift.h"
#import "ProjectName_Summary-Swift.h"
#import "ProjectName_WatchKit_Extension-Swift.h"
EDIT 4: Visibilité croisée des fichiers -Swift.h
J'ai essayé ce qui suit:
Lorsque la classe Swift est définie pour plusieurs cibles et que le fichier ObjectiveC est utilisé par ces cibles multiples, cela ne fonctionne pas. Les erreurs de construction sont les suivantes: Target X -> Fichier "ProjectName_TargetY-Swift.h" introuvable . Apparemment, une cible ne peut pas voir les autres fichiers de cibles -Swift.h.
Qu'est-ce que je fais mal? Merci pour votre aide
L’hypothèse que j’ai faite dans Edit 4 s’est avérée être la bonne . Si un projet a plusieurs cibles, les fichiers "-Swift.h" ne peuvent pas être importés dans un fichier .m ObjectiveC.
Il faut donc adopter une solution: modifier le paramètre de construction Swift_OBJC_INTERFACE_HEADER_NAME et le rendre identique pour différentes cibles . Pour ce faire, modifiez l'instruction qui génère cette propriété à partir de $ (Swift_MODULE_NAME ) -Swift.h à $ (PROJECT_NAME) -Swift.h comme expliqué ici
Il est également possible de définir le paramètre Nom du module de produit dans les paramètres de construction de manière à ce qu'il soit identique dans tous vos modules (je l'ai défini sur $ (PROJECT_NAME)), de sorte que le fichier -Swift.h généré soit identique dans tous les modules. . Cela élimine la nécessité d'ajouter/de vérifier les macros du préprocesseur.
Après avoir nettoyé le dossier de construction, appuyez sur Alt et accédez au menu Produit. Comme le nom de l'en-tête est partagé entre les cibles, il peut maintenant être importé une fois dans le fichier .m ObjectiveC et toutes les cibles peuvent bénéficier des classes Swift.
Si, après la construction, l'erreur persiste, assurez-vous que l'en-tête est accessible à partir de XCode en cliquant sur son nom. Il devrait ouvrir un fichier contenant du code similaire à ceci:
Swift_CLASS("_TtC27ProjectName_Summary11MyClass")
@interface MyClass : NSObject
- (nonnull instancetype)init OBJC_DESIGNATED_INITIALIZER;
@end
Si vous devez vous assurer que ces en-têtes sont générés, ouvrez un terminal et utilisez cette commande
find ~/Library/Developer/Xcode/DerivedData -name "*Swift.h"
Vous devriez voir un en-tête pour chaque cible
Un autre problème qui m’est arrivé après ces changements est qu’il a commencé à donner des erreurs sur le code ObjectiveC que je n’ai pas touchées. Le problème était dû à la position de l'importation, comme indiqué ici :
En haut du fichier .m, vous importez l'en-tête de pontage masqué qui peut faire la différence. Le signe habituel de problème est que vous obtenez une erreur de compilation «Nom de type inconnu», où le type inconnu est une classe déclarée dans Objective-C. La solution consiste à # importer le fichier .h contenant également la déclaration du type inconnu dans vos fichiers Objective-C, avant d'importer l'en-tête de pontage masqué. Cela peut être une gêne, en particulier si le fichier Objective-C en question n'a pas besoin de connaître cette classe, mais qu'il résout le problème et permet à la compilation de continuer.
A la toute fin, le code est compilé et exécuté sur un appareil et un simulateur!
La solution pour moi consistait à importer l'en-tête Swift généré via la syntaxe <>
:
#import <OtherTargetWithSwiftClass/OtherTargetWithSwiftClass-Swift.h>
Ce n'est pas une solution à la question mais beaucoup d'entre eux pourraient se retrouver sur cette page à la recherche du problème que le fichier <ModuleName>-Swift.h
est introuvable (tout comme moi). J'aimerais ajouter une raison supplémentaire:
Lorsqu'il y a un problème de compilation dans un fichier Swift, l'en-tête peut ne pas être généré par Xcode et le fichier est donc manquant.
Au moins dans mon cas, le <ModuleName>-Swift.h not found
avait disparu une fois que j'avais corrigé l'erreur de compilation dans le fichier Swift.
J'avais un problème similaire et j'ai presque fini par passer toute une journée à résoudre le problème tout en suivant les suggestions d'autres développeurs sur StackOverflow et quelques autres sources.
J'étais en train de passer de Xcode 7.3.1 à Xcode 8.2.1 et de Swift 2.2 à Swift 3.0.1.
Dans mon cas, j'ai découvert que le fichier PROJECT_NAME-Swift.h
n'a pas été créé à:
~/Library/Developer/Xcode/DerivedData/PRODUCT-NAME-hdkrxixrxbiorwesffpqvefxsrzl/Build/Intermediates/PRODUCT-NAME.build/Debug/PRODUCT-NAME.build/Objects-normal/x86_64/PRODUCT-NAME-Swift.h.
J'imagine qu'il essaie en quelque sorte de faire référence à ce fichier d'en-tête à partir du chemin ci-dessus et donc de l'erreur. Je l'ai copié manuellement. N'a pas fait de nouvelle génération après cela . Cela a résolu mon problème et le fichier d'en-tête Swift a commencé à être créé pour une compilation et des générations supplémentaires.
Dans mon cas, j'ai un espace de travail avec un sous-projet d'application iOS, un sous-projet d'infrastructure et un sous-projet CocoaPods Pods. L'erreur "Fichier ModuleName-Swift.h introuvable" s'est produite dans mon sous-projet de cadre car le fichier n'avait pas encore été créé par le sous-projet Pods.
Je ne sais pas s'il existe un moyen de renseigner Xcode sur les dépendances entre sous-projets, mais je les ai simplement réordonnés dans le navigateur de projet de gauche:
A bien fonctionné après ça!
Pour mon cas, cela fonctionne bien dans Xcode 8 mais les fichiers avec
#import "Project-Swift.h"
a des importations manquantes comme décrit par LucioB
Utiliser Xcode 9 supprime ces erreurs