web-dev-qa-db-fra.com

Impossible d'utiliser les classes Swift dans Objective-C

J'essaie d'intégrer le code Swift dans mon application. Mon application est écrite en Objective-C et j'ai ajouté une classe Swift. J'ai tout fait décrit ici . Mais mon problème est que Xcode n'a pas créé le fichier -Swift.h, mais uniquement les en-têtes de pontage. Donc je l’ai créé, mais c’est en fait vide… .. Je peux utiliser toutes mes classes ObjC dans Swift, mais je ne peux pas le faire inversement. J'ai marqué ma classe Swift avec @objc mais cela n'a pas aidé. Que puis-je faire maintenant?

EDIT: Apple déclare: "Lorsque vous importez du code Swift dans Objective-C, vous comptez sur un fichier d’entête Xcode-generated pour exposer ces fichiers à Objective-C. "-Swift.h". "

Maintenant, quand je veux importer ce fichier, cela donne une erreur:

    //MainMenu.m

    #import "myProjectModule-Swift.h" //Error: 'myProjectModule-Swift.h' file not found

    @implementation MainMenu

Voici mon fichier FBManager.Swift:

@objc class FBManager: NSObject {

    var descr = "FBManager class"

    init() {
        super.init()
    }

    func desc(){
        println(descr)
    }

    func getSharedGameState() -> GameState{
        return GameState.sharedGameState() //OK! GameState is written in Objective-C and no error here
    }
}
233
D Nagy

J'ai passé environ 4 heures à essayer d'activer Swift dans mon projet Xcode basé sur Objective-C. Mon fichier "myproject-Swift.h" a été créé avec succès, mais ma Xcode n'a pas vu mon Swift-classes. J'ai donc décidé de créer un nouveau projet Xcode basé sur Objc et j'ai finalement trouvé la bonne réponse! J'espère que ce post aidera quelqu'un :-)

Intégration Swift pas à pas pour les projets basés sur Xcode Objc:

  1. Créez un nouveau fichier *.Swift (dans Xcode) ou ajoutez-le à l'aide du Finder
  2. Créez un Objective-C bridging header quand Xcode vous le demandera
  3. Implémentez votre classe Swift:

    import Foundation
    
    // use @objc or @objcMembers annotation if necessary
    class Foo {
        //..
    }
    
  4. Ouvrez les paramètres de construction et vérifiez ces paramètres:

    • Defines Module: YES

      Copier et coller le nom du paramètre dans une barre de recherche

    • Nom du module de produit: myproject

      Assurez-vous que votre nom de module de produit ne contient aucun caractère spécial

    • Installez l'en-tête de compatibilité Objective-C: YES

      Une fois que vous avez ajouté le fichier *.Swift au projet, cette propriété apparaît dans les paramètres de construction.

    • En-tête d'interface généré par Objective-C: myproject-Swift.h.____.

      Cet en-tête est généré automatiquement par Xcode.

    • En-tête de pontage Objective-C: $(SRCROOT)/myproject-Bridging-Header.h
  5. Importer l'en-tête d'interface Swift dans votre fichier * .m

    #import "myproject-Swift.h"
    

    Ne faites pas attention aux erreurs et aux avertissements.

  6. Nettoyer et reconstruire votre projet Xcode
  7. Profit!
484
sig

Ne créez pas le fichier d'en-tête vous-même. Supprimez celui que vous avez créé.

Assurez-vous que vos classes Swift portent la balise @objc ou héritent d'une classe dérivée (directement ou indirectement) de NSObject.

Xcode ne générera pas le fichier si vous rencontrez des erreurs de compilation dans votre projet. Assurez-vous que votre projet est construit correctement.

61
Bill

Autoriser Xcode à faire son travail, ne pas ajouter/créer d'en-tête Swift manuellement. Ajoutez simplement @objc avant votre classe Swift ex. 

@objc class YourSwiftClassName: UIViewController

Dans le cadre de votre projet, recherchez les indicateurs ci-dessous et remplacez-le par OUI (projet et cible).

Defines Module : YES
Always Embed Swift Standard Libraries : YES
Install Objective-C Compatibility Header : YES

Nettoyez ensuite le projet et générez-le une fois. Une fois la construction réussie (probablement), importez-le sous le fichier d'en-tête de votre fichier .m

#import "YourProjectName-Swift.h" 

Boooom!

33
Bharat Modi

Aussi probablement utile pour ceux d'entre vous avec une cible Framework:

L'instruction import du fichier d'en-tête généré automatiquement ressemble un peu différent des cibles de l'application. En plus des autres choses mentionnées dans d’autres réponses, utilisez

#import <ProductName/ProductModuleName-Swift.h>

au lieu de

#import "ProductModuleName-Swift.h"

conformément à la documentation Apples sur Mix & Match pour les objectifs-cadres.

27
Dschee

Assurez-vous que votre projet définit un module et que vous en avez donné un nom. Ensuite, reconstruisez, et Xcode créera le fichier d’en-tête -Swift.h et vous pourrez importer.

Vous pouvez définir la définition et le nom du module dans les paramètres de votre projet.

14
Leo Natan

J'ai eu le même problème et il s'est avéré que des symboles spéciaux dans le nom du module sont remplacés par xcode (dans mon cas, les tirets étaient des traits de soulignement). Dans les paramètres du projet, cochez "nom du module" pour trouver le nom du module pour votre projet. Après cela, utilisez ModuleName-Swift.h ou renommez le module dans les paramètres.

11
Max Mikheyenko

Détails: Projet Objective-C avec code Swift 3 dans Xcode 8.1

Les tâches:

  1. Utilisez Swift enum en objective-c class
  2. Utilisez objective-c enum en classe Swift 

Échantillon complet

1. Classe Objective-C utilisant Swift enum

ObjcClass.h

#import <Foundation/Foundation.h>

typedef NS_ENUM(NSInteger, ObjcEnum) {
    ObjcEnumValue1,
    ObjcEnumValue2,
    ObjcEnumValue3
};

@interface ObjcClass : NSObject

+ (void) PrintEnumValues;

@end

ObjcClass.m

#import "ObjcClass.h"
#import "SwiftCode.h"

@implementation ObjcClass

+ (void) PrintEnumValues {
    [self PrintEnumValue:SwiftEnumValue1];
    [self PrintEnumValue:SwiftEnumValue2];
    [self PrintEnumValue:SwiftEnumValue3];
}

+ (void) PrintEnumValue:(SwiftEnum) value {
    switch (value) {
        case SwiftEnumValue1:
            NSLog(@"-- SwiftEnum: SwiftEnumValue1");
            break;

        case SwiftEnumValue2:
        case SwiftEnumValue3:
            NSLog(@"-- SwiftEnum: long value = %ld", (long)value);
            break;
    }
}

@end

Détecter le code Swift dans le code Objective-C

Dans mon exemple, j'utilise SwiftCode.h pour détecter le code Swift dans Objective-C. Ce fichier génère automatiquement (je n'ai pas créé de copie physique de ce fichier d'en-tête dans un projet), et vous pouvez uniquement définir le nom de ce fichier: 

 enter image description here

 enter image description here

Si le compilateur ne trouve pas votre code Swift dans le fichier d’en-tête, essayez de compiler le projet.

2. Classe Swift qui utilise Objective-C enum

import Foundation

@objc
enum SwiftEnum: Int {
    case Value1, Value2, Value3
}

@objc
class SwiftClass: NSObject {

    class func PrintEnumValues() {
        PrintEnumValue(.Value1)
        PrintEnumValue(.Value2)
        PrintEnumValue(.Value3)
    }

    class func PrintEnumValue(value: ObjcEnum) {
        switch value {
        case .Value1, .Value2:
            NSLog("-- ObjcEnum: int value = \(value.rawValue)")

        case .Value3:
            NSLog("-- ObjcEnum: Value3")
            break
        }

    }
}

Détecter le code Objective-C dans le code Swift

Vous devez créer un fichier d'en-tête de pontage. Lorsque vous ajoutez un fichier Swift dans un projet Objective-C ou un fichier Objective-C dans un projet Swift, Xcode vous suggère de créer un en-tête de pontage.

 enter image description here

Vous pouvez modifier le nom du fichier d'en-tête de pontage ici:

 enter image description here

Bridging-Header.h

#import "ObjcClass.h"

Usage

#import "SwiftCode.h"
...
[ObjcClass PrintEnumValues];
[SwiftClass PrintEnumValues];
[SwiftClass PrintEnumValue:ObjcEnumValue3];

Résultat

 enter image description here


PLUS D'ÉCHANTILLONS

Etapes d'intégration complète Objective-c et Swift décrites ci-dessus. Maintenant, je vais écrire d'autres exemples de code.

3. Appelez la classe Swift à partir du code Objective-c

Classe rapide

import Foundation

@objc
class SwiftClass:NSObject {

    private var _stringValue: String
    var stringValue: String {
        get {
            print("SwiftClass get stringValue")
            return _stringValue
        }
        set {
            print("SwiftClass set stringValue = \(newValue)")
            _stringValue = newValue
        }
    }

    init (stringValue: String) {
        print("SwiftClass init(String)")
        _stringValue = stringValue
    }

    func printValue() {
        print("SwiftClass printValue()")
        print("stringValue = \(_stringValue)")
    }

}

Code Objective-C (code d'appel)

SwiftClass *obj = [[SwiftClass alloc] initWithStringValue: @"Hello World!"];
[obj printValue];
NSString * str = obj.stringValue;
obj.stringValue = @"HeLLo wOrLd!!!";

Résultat

 enter image description here

4. Appelez la classe Objective-c à partir du code Swift

Classe Objective-C (ObjcClass.h)

#import <Foundation/Foundation.h>

@interface ObjcClass : NSObject
@property NSString* stringValue;
- (instancetype) initWithStringValue:(NSString*)stringValue;
- (void) printValue;
@end

ObjcClass.m

#import "ObjcClass.h"

@interface ObjcClass()

@property NSString* strValue;

@end

@implementation ObjcClass

- (instancetype) initWithStringValue:(NSString*)stringValue {
    NSLog(@"ObjcClass initWithStringValue");
    _strValue = stringValue;
    return self;
}

- (void) printValue {
    NSLog(@"ObjcClass printValue");
    NSLog(@"stringValue = %@", _strValue);
}

- (NSString*) stringValue {
    NSLog(@"ObjcClass get stringValue");
    return _strValue;
}

- (void) setStringValue:(NSString*)newValue {
    NSLog(@"ObjcClass set stringValue = %@", newValue);
    _strValue = newValue;
}

@end

Code Swift (code d'appel)

if let obj = ObjcClass(stringValue:  "Hello World!") {
    obj.printValue()
    let str = obj.stringValue;
    obj.stringValue = "HeLLo wOrLd!!!";
}

Résultat

 enter image description here

5. Utiliser l'extension Swift dans le code Objective-c

Extension rapide

extension UIView {
    static func swiftExtensionFunc() {
        NSLog("UIView swiftExtensionFunc")
    }
}

Code Objective-C (code d'appel)

[UIView swiftExtensionFunc];

6. Utiliser l'extension Objective-c dans le code Swift

Extension Objective-C (UIViewExtension.h)

#import <UIKit/UIKit.h>

@interface UIView (ObjcAdditions)
+ (void)objcExtensionFunc;
@end

UIViewExtension.m

@implementation UIView (ObjcAdditions)
+ (void)objcExtensionFunc {
    NSLog(@"UIView objcExtensionFunc");
}
@end

Code Swift (code d'appel)

UIView.objcExtensionFunc()
11
Vasily Bodnarchuk

Le fichier est créé automatiquement (en parlant de Xcode 6.3.2 ici). Mais vous ne le verrez pas, car il se trouve dans votre dossier Derived Data. Après avoir marqué votre classe Swift avec @objc, compilez-le, puis recherchez Swift.h dans votre dossier Derived Data. Vous devriez trouver l'en-tête Swift ici.

Le problème est que Xcode a renommé mon my-Project-Swift.h en my_Project-Swift.h. Xcode n’aime pas les symboles "." "-" etc. Avec la méthode ci-dessus, vous pouvez trouver le nom du fichier et l'importer dans une classe Objective-C.

9
brainray

Il suffit d'inclure #import "myProject-Swift.h" dans un fichier .m ou .h

P.S Vous ne trouverez pas "myProject-Swift.h" dans l'inspecteur de fichiers, il est masqué. Mais il est généré automatiquement par l'application.

8
Svitlana

@sig answer est l'un des meilleurs, cependant cela ne fonctionnait pas pour moi avec l'ancien projet (pas nouveau!), j'avais besoin de quelques modifications. Après de nombreuses variantes, j'ai trouvé la recette (en utilisant XCode 7.2):

  1. Nom du module de produit: $ (PRODUCT_NAME: c99extidentifier) 
  2. Définit le module: NON
  3. Le contenu intégré contient Swift: NO
  4. Installer l'en-tête de compatibilité Objective-C: YES
  5. En-tête de pontage Objective-C: ProjectName-Bridging-Header.h

Le dernier point (5) était crucial. Je le mets uniquement sur la deuxième section (champ Cibles), le champ Projet doit rester vide:  enter image description here Sinon, il ne m'a pas généré le fichier "Project-Swift.h" correct (il n'incluait pas les méthodes Swift).

4
Darius Miliauskas

Il y a deux conditions,

  • Utilisez votre fichier Swift dans le fichier Objective C.
  • Utilisez votre fichier Objective C dans le fichier Swift.

Alors, pour cela, vous devez suivre ces étapes:

  • Ajoutez votre fichier Swift à un projet objective-c ou inversement.
  • Créer un fichier d'en-tête (.h).
  • Allez dans Configurer les paramètres et effectuez les étapes ci-dessous avec la recherche, 

    1. recherchez ce texte "brid" et définissez un chemin d'accès à votre fichier d'en-tête.
    2. "Module défini": OUI. 
    3. "Toujours intégrer les bibliothèques standard Swift": OUI. 
    4. "Installer l'en-tête de compatibilité Objective-C": OUI.

Après cela, nettoyez et reconstruisez votre projet.

Utilisez votre fichier Swift dans le fichier Objective C.

Dans ce cas, écrivez d'abord "@objc" avant votre classe dans le fichier Swift.

Après cela, dans votre fichier Objective C, écrivez ceci,

  #import "YourProjectName-Swift.h"

Utilisez votre fichier Objective C dans le fichier Swift.

Dans ce cas, dans votre fichier d'en-tête, écrivez ceci,

  #import "YourObjective-c_FileName.h"

J'espère que cela t'aidera.

4
vikas prajapati

Dans mon cas, en dehors de ces étapes:

  1. Nom du module de produit: myproject
  2. Defines Module: OUI
  3. Le contenu incorporé contient Swift: YES
  4. Installer l'en-tête de compatibilité Objective-C: YES
  5. En-tête de pontage Objective-C: $ (SRCROOT) /Sources/SwiftBridging.h

J'ai eu besoin de mettre la classe comme public pour créer productName-Swift.h fichier:

import UIKit

   @objc public class TestSwift: NSObject {
       func sayHello() {
          print("Hi there!")
       }
   }
3
Saúl Moreno Abril

J'ai eu le même problème et finalement, il est apparu qu'ils n'étaient pas attachés aux mêmes objectifs. La classe ObjC est attachée à Target1 et Target2, la classe Swift n'est attachée qu'à Target1 et n'est pas visible à l'intérieur de la classe ObjC.

J'espère que ça aide quelqu'un.

2
Dani.Rangelov

Je viens de découvrir que l'ajout d'un répertoire de fichiers Swift à un projet ne fonctionnera pas. Vous devez d'abord créer un groupe pour le répertoire, puis ajouter les fichiers Swift ...

2
Darren Ehlers

Utilisation de Swift Classes en Objective-C

Si vous envisagez d'importer du code dans une cible d'application (en mélangeant Objective-C et Swift dans un projet), vous devez utiliser la ligne d'importation suivante #import "<#YourProjectName#>-Swift.h" pour afficher le code Swift. au code Objective-C [Mélange Swift et code Objective-C dans un projet]

Dans ce post, je vais décrire comment importer Swift bibliothèque statique en code Objective-C

Consommateur Objective-C -> Swift bibliothèque statique

Xcode version 10.2.1

Créer une bibliothèque statique Swift

Créer un projet de bibliothèque ou créer une cible de bibliothèque

File -> New -> Project... -> Cocoa Touch Static Library
//or
Project editor -> Add a Target -> Cocoa Touch Static Library 

Ajouter des fichiers .Swift

Select `.Swift` file -> Select File Inspectors Tab -> Target Membership -> Select the target
//or
Project editor -> select a target -> Build Phases -> Compile Sources -> add files

Exposer Swift API. Pour utiliser les fonctions de Swift depuis Objective-C [À propos]

Construire une bibliothèque - ⌘ Command + B ou Product -> Build

Remarque: assurez-vous de créer la bibliothèque pour la même architecture de processus que le code client.

Trouver la sortie générée [Lieu de construction]

Products group -> lib<product_name>.a -> Show in Finder

Le répertoire comprend

  • lib<product_name>.a - une bibliothèque statique construite
  • <product_name>.swiftmodule dossier qui comprend:
    • .swiftdoc - docs
    • .swiftmodule - interface publique/définitions

Aussi, vous devriez trouver un fichier <product_name>-Swift.h qui devrait être situé dans DerivedSources[Fichier non trouvé]

Utilisation de la bibliothèque statique Swift

Drag and drop le binaire dans le projet Xcode [À propos]

Link Library[Symboles non définis][Lien vs Intégrer]

Project editor -> select a target -> General -> Linked Frameworks and Libraries -> add -> Add Others... -> point to `lib<product_name>.a` file
//or
Project editor -> select a target -> Build Phases -> Link Binary With Libraries -> add -> Add Others... -> point to `lib<product_name>.a` file

Ajouter Library Search paths[Bibliothèque introuvable pour][Chemin récursif]

Project editor -> select a target -> Build Settings -> Search Paths -> Library Search paths -> add path to the parent of `lib<product_name>.a` file

Ajouter Header Search Paths[Module non trouvé][Chemin récursif]

Project editor -> select a target -> Build Settings -> Search Paths -> Header Search Paths -> add path to generated `<product_name>-Swift.h` file 

Ajoutez .Swift file vide au projet Objective-C . [Symboles non définis] Lorsque Xcode demande, appuyez sur Create Bridging Header (il créera module_name-Bridging-Header.h) et définissez un chemin vers ce fichier dans

Project editor -> select a target -> Build Settings -> Swift Compiler - General -> Objective-C Bridging Header

Module d'importation dans le code client Objective-C [Fichier non trouvé] [nom_module]

#import "module_name-Swift.h"

Plus d'exemples ici

1
yoAlex5

Pour Swift 5:

  1. Ajoutez le mot clé @objc à votre classe et à vos méthodes
  2. Ajoutez le mot clé public à votre classe et à vos méthodes
  3. Laissez votre classe hériter de NSObject
  4. Projet de construction
  5. Mettez #import "MyProject-Swift.h" dans votre fichier Objective-C

    @objc
    public class MyClass: NSObject {
    
        @objc
        public func myMethod() {
    
        }
    }
    
0
Nico S.

J'avais des problèmes en ce sens que j'ajouterais des classes à mon en-tête de transition objective-c, et dans les en-têtes d'objectif-c importés, ils essayaient d'importer l'en-tête Swift. Ça n'a pas aimé ça.

Ainsi, dans toutes mes classes objective-c qui utilisent Swift, mais sont également pontées, la clé était de vous assurer que vous utilisez les déclarations de classe en aval dans les en-têtes, puis importez le fichier "* -Swift.h" dans le fichier .m.

0
horseshoe7

Je n'ai pas eu à modifier les paramètres de la construction ni à ajouter @obj à la classe.

Tout ce que j'avais à faire était de créer un en-tête de pont qui a été créé automatiquement lorsque j'ai créé des classes Swift dans un projet Objective-c. Et puis je devais juste faire

importer "Bedtime-Swift.h" <- dans le fichier objective-c devant utiliser ce fichier Swift.

0
coolcool1994

Lorsque vous ajoutez de nouveaux fichiers Swift au projet, assurez-vous de les ajouter aux cibles appropriées. Assurez-vous que tous les fichiers Swift que vous allez utiliser héritent de la classe NSObject et sont annotés avec @ObjCMembers Passez à YES dans les paramètres de construction sous l'option ALWAYS_EMBED_Swift_STANDARD_LIBRARIES. Passez à OUI dans les paramètres de construction de l'option DEFINES_MODULE.

0
Boris

mon problème était que je me suis retrouvé coincé après que xcode ait créé le fichier bridge, mais j'ai toujours une erreur dans le nom du fichier d'en-tête MYPROJECTNAME-Swift.h 

1.J'enregistre dans le terminal et recherche tous les fichiers de pont Swift créés automatiquement:

find ~/library/Developer/Xcode/DerivedData/ -name "*-Swift.h"|xargs basename|sort -

vous voyez quel xcode créé.

  1. dans mon cas, j'avais un espace dans le nom de mon projet et xcode remplace c'est '_'
0
user1105951

Mon problème était que la génération automatique du fichier -Swift.h n'était pas capable de comprendre une sous-classe de CustomDebugStringConvertible. J'ai changé la classe pour être une sous-classe de NSObject à la place. Après cela, le fichier -Swift.h incluait maintenant correctement la classe.

0
Justin Domnitz

eh bien, après avoir lu tous les commentaires et essayé encore et encore, j’ai réussi à inclure des classes Swift dans mon projet Big obj-c . Alors, merci pour toute l’aide . Je voulais partager un conseil qui m'a aidé à mieux comprendre le processus . Dans la classe .m, est allé à la ligne d'importation du nom de la cible Swift #import "myTargetName-Swift.h" et a cliqué sur la clé:

commande + clic de souris -> Aller à la définition  enter image description here

Là, vous pouvez voir toute la traduction de Swift en obj-c et vous y trouverez les différentes fonctions déclarées à nouveau dans obj-c . J'espère que ce conseil vous aidera autant qu'il m'a aidé.

0
Techno Mag

J'ai la même erreur: myProjectModule-Swift.h fichier non trouvé ", mais dans mon cas, la vraie raison était dans la cible de déploiement incorrecte: " Swift n'est pas disponible sur OS X antérieure à 10.9; veuillez définir MACOSX_DEPLOYMENT_TARGET sur 10.9 ou ultérieur (actuellement, il s'agit de '10 .7 ') " Ainsi, lorsque j'ai modifié la cible de déploiement en 10.9 - le projet a été compilé avec succès.

0
slavik