Comment appeler le code Objective-C depuis Swift?


974

Dans Swift, comment appelle-t-on le code Objective-C?

Apple a mentionné qu'ils pouvaient coexister dans une seule application, mais cela signifie-t-il que l'on pourrait techniquement réutiliser les anciennes classes faites en Objective-C tout en construisant de nouvelles classes dans Swift?


13
Consultez le guide d'Apple sur l' utilisation de Swift avec Cocoa et Objective-C .
rickster


10
Intéressant que cette question reçoive autant de votes positifs et une prime. Quand je l'ai vu pour la première fois, j'ai pensé: RTFM. Tel qu'il est posé, il ne montre vraiment aucune recherche, car il n'y a actuellement que deux ou trois ressources qui documentent officiellement Swift, et l'une d'entre elles est entièrement dédiée à cela (et est liée à dans le premier commentaire).
Fichier analogique

6
@EvolGate: qu'est-ce qui manque exactement à Objective C qui l'empêche d'être un langage indépendant de la plateforme? La langue et les bibliothèques standard de langue sont open source. Vous pouvez utiliser Objective C dans et pour Windows, Os X, Linux, BSD, Solaris et toute autre plate-forme prise en charge par GCC ou LLVM. Vous pouvez facilement porter Objective C sur n'importe quelle plate-forme avec un compilateur C décent même s'il n'est pris en charge ni par GCC ni par LLVM. Je ne vois pas comment cela pourrait être plus indépendant de la plate-forme que cela.
Fichier analogique

2
@DavidMulder: la section "Le raisonnement" est-elle toujours nécessaire?
franck

Réponses:


1395

Utilisation de classes Objective-C dans Swift

Si vous avez une classe existante que vous souhaitez utiliser, effectuez l' étape 2 , puis passez à l' étape 5 . (Dans certains cas, j'ai dû ajouter un explicite #import <Foundation/Foundation.hà un fichier Objective-C plus ancien.)

Étape 1: Ajouter une implémentation Objective-C - .m

Ajoutez un .mfichier à votre classe et nommez-le CustomObject.m.

Étape 2: ajouter un en-tête de pontage

Lors de l'ajout de votre .mfichier, vous serez probablement frappé par une invite qui ressemble à ceci:

Une boîte de dialogue de style feuille MacOS de Xcode vous demandant si vous souhaitez "configurer un en-tête de pontage Objective-C"

Cliquez sur Oui !

Si vous n'avez pas vu l'invite ou supprimé accidentellement votre en-tête de pontage, ajoutez un nouveau .hfichier à votre projet et nommez-le <#YourProjectName#>-Bridging-Header.h.

Dans certaines situations, en particulier lorsque vous travaillez avec des frameworks Objective-C, vous n'ajoutez pas explicitement une classe Objective-C et Xcode ne peut pas trouver l'éditeur de liens. Dans ce cas, créez votre .hfichier nommé comme mentionné ci-dessus, puis assurez-vous de lier son chemin dans les paramètres de projet de votre cible comme suit:

Une animation illustrant le paragraphe ci-dessus

Remarque:

Il est recommandé de lier votre projet à l'aide de la $(SRCROOT)macro de sorte que si vous déplacez votre projet ou travaillez dessus avec d'autres à l'aide d'un référentiel distant, il fonctionnera toujours. $(SRCROOT)peut être considéré comme le répertoire contenant votre fichier .xcodeproj. Cela pourrait ressembler à ceci:

$(SRCROOT)/Folder/Folder/<#YourProjectName#>-Bridging-Header.h

Étape 3: ajouter un en-tête Objective-C - .h

Ajoutez un autre .hfichier et nommez-le CustomObject.h.

Étape 4: Créez votre classe Objective-C

Dans CustomObject.h

#import <Foundation/Foundation.h>

@interface CustomObject : NSObject

@property (strong, nonatomic) id someProperty;

- (void) someMethod;

@end

Dans CustomObject.m

#import "CustomObject.h"

@implementation CustomObject 

- (void) someMethod {
    NSLog(@"SomeMethod Ran");
}

@end

Étape 5: ajouter une classe à l'en-tête de pontage

Dans YourProject-Bridging-Header.h:

#import "CustomObject.h"

Étape 6: utilisez votre objet

Dans SomeSwiftFile.swift:

var instanceOfCustomObject = CustomObject()
instanceOfCustomObject.someProperty = "Hello World"
print(instanceOfCustomObject.someProperty)
instanceOfCustomObject.someMethod()

Il n'est pas nécessaire d'importer explicitement; c'est à cela que sert l'en-tête de pontage.

Utilisation de classes Swift dans Objective-C

Étape 1: créer une nouvelle classe Swift

Ajoutez un .swiftfichier à votre projet et nommez-le MySwiftObject.swift.

Dans MySwiftObject.swift:

import Foundation

@objc(MySwiftObject)
class MySwiftObject : NSObject {

    @objc
    var someProperty: AnyObject = "Some Initializer Val" as NSString

    init() {}

    @objc
    func someFunction(someArg: Any) -> NSString {
        return "You sent me \(someArg)"
    }
}

Étape 2: importer des fichiers Swift dans la classe ObjC

Dans SomeRandomClass.m:

#import "<#YourProjectName#>-Swift.h"

Le fichier: <#YourProjectName#>-Swift.hdoit déjà être créé automatiquement dans votre projet, même si vous ne le voyez pas.

Étape 3: utilisez votre classe

MySwiftObject * myOb = [MySwiftObject new];
NSLog(@"MyOb.someProperty: %@", myOb.someProperty);
myOb.someProperty = @"Hello World";
NSLog(@"MyOb.someProperty: %@", myOb.someProperty);

NSString * retString = [myOb someFunctionWithSomeArg:@"Arg"];

NSLog(@"RetString: %@", retString);

Remarques:

  1. Si la complétion de code ne se comporte pas comme prévu, essayez d'exécuter une construction rapide avec Rpour aider Xcode à trouver une partie du code Objective-C dans un contexte Swift et vice versa.

  2. Si vous ajoutez un .swiftfichier à un ancien projet et obtenez l'erreur dyld: Library not loaded: @rpath/libswift_stdlib_core.dylib, essayez de redémarrer complètement Xcode .

  3. Alors qu'il était à l'origine possible d'utiliser des classes Swift pures (pas des descendants de NSObject) qui sont visibles pour Objective-C en utilisant le @objcpréfixe, ce n'est plus possible. Maintenant, pour être visible dans Objective-C, l'objet Swift doit soit être une classe conforme à NSObjectProtocol(la façon la plus simple de le faire est d'hériter de NSObject), soit être enummarqué @objcavec une valeur brute d'un type entier comme Int. Vous pouvez afficher l'historique des modifications pour un exemple de code Swift 1.x utilisant @objcsans ces restrictions.


5
Il est important d'annoter les méthodes avec @objc ou les méthodes Swift ne seront pas visibles depuis Objective-C.
Tomáš Linhart

29
Tu as raison. Vous devez uniquement le spécifier si vous n'utilisez pas d'objets Cocoa. Pour être accessible et utilisable dans Objective-C, une classe Swift doit être un descendant d'une classe Objective-C ou elle doit être marquée @objc.
Tomáš Linhart


2
Voir aussi: WWDC 2014 Session 406: Integrating Swift with Objective-C
Stuart M

6
Si vous importez un framework Objective C dans Swift, assurez-vous d'importer tous les frameworks dont dépend le framework Obj C dans votre projet (dans Build Phases -> Link Binary With Libraries), puis ajoutez # import's for these to a prefix header file, which doit être ajouté à votre projet dans les paramètres de construction (dans le champ En-tête de préfixe). Cela inclut des frameworks comme UIKit et Foundation, même s'ils sont déjà utilisés à partir de Swift. Cela m'a fait trébucher pendant des heures, et personne ne semble avoir documenté ces étapes.
user1021430

121

Consultez le guide d'Apple sur l' utilisation de Swift avec Cocoa et Objective-C . Ce guide explique comment utiliser le code Objective-C et C de Swift et vice versa et contient des recommandations sur la façon de convertir un projet ou de mélanger et de faire correspondre des pièces Objective-C / C et Swift dans un projet existant.

Le compilateur génère automatiquement la syntaxe Swift pour appeler les fonctions C et les méthodes Objective-C. Comme vu dans la documentation, cet Objective-C:

UITableView *myTableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStyleGrouped];

se transforme en ce code Swift:

let myTableView: UITableView = UITableView(frame: CGRectZero, style: .Grouped)

Xcode effectue également cette traduction à la volée - vous pouvez utiliser Ouvrir rapidement pendant la modification d'un fichier Swift et taper un nom de classe Objective-C, et cela vous amènera à une version Swift-ified de l'en-tête de classe. (Vous pouvez également l'obtenir en cliquant sur un symbole d'API dans un fichier Swift.) Et toute la documentation de référence de l'API dans les bibliothèques de développement iOS 8 et OS X v10.10 (Yosemite) est visible dans Objective-C et Swift formes (par exemple UIView).


3
Le lien direct vers la documentation Apple comment intégrer Swift dans un projet existant: developer.apple.com/library/prerelease/ios/documentation/Swift/…
skywinder

Si nous voulons savoir pourquoi les fichiers d'en-tête sont nécessaires et comment ils sont utilisés pendant la phase de liaison, assurez-vous de lire ce manuel Swift: Comprendre le pipeline de construction Swift / Objective-C
Honey

62

Voici des instructions pas à pas pour utiliser le code Objective-C (dans ce cas, un framework fourni par un tiers) dans un projet Swift:

  1. Ajoutez un fichier Objective-C à votre projet Swift en choisissant Fichier -> Nouveau -> Nouveau fichier -> Fichier Objective-C. Lors de l'enregistrement, Xcode vous demandera si vous souhaitez ajouter un en-tête de pontage . Choisissez « Oui ». (source: derrrick.com )Gif: ajouter un fichier vide au projet et générer un en-tête de pontage

En quelques étapes simples:

  1. Une invite apparaît, puis cliquez sur OK ... S'il n'apparaît pas, nous le créons manuellement comme dans l'exemple suivant ... Créez un fichier d'en-tête à partir de la source iOS et donnez le nom ProjectName-Bridging-Header (exemple: Test -Bridging-Header), puis accédez au paramètre de génération dans le code du compilateur Swift -> Pont Objective-C, ajoutez le nom du pont Objective-C .. (Test / Test-Bridging-Header.h). Ouais, c'est complet.

  2. Facultativement, supprimez le fichier Objective-C que vous avez ajouté (nommé "n'importe quoi" dans l'image GIF ci-dessus). Vous n'en avez plus besoin.

  3. Ouvrez le fichier d'en-tête de pontage - le nom de fichier est au format [YourProject] -Bridging-Header.h . Il comprend un commentaire fourni par Xcode. Ajoutez une ligne de code pour le fichier Objective-C que vous souhaitez inclure , tel qu'un framework tiers. Par exemple, pour ajouter Mixpanel à votre projet, vous devrez ajouter la ligne de code suivante au fichier d'en-tête de pontage:

    #import "Mixpanel.h"
  4. Maintenant, dans n'importe quel fichier Swift, vous pouvez utiliser le code Objective-C existant, dans la syntaxe Swift (dans le cas de cet exemple, et vous pouvez appeler les méthodes Mixpanel SDK, etc.). Vous devez vous familiariser avec la façon dont Xcode traduit Objective-C en Swift. Le guide d'Apple est une lecture rapide. Ou consultez cette réponse pour un résumé incomplet.

Exemple pour Mixpanel:

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
    Mixpanel.sharedInstanceWithToken("your-token")
    return true
}

C'est ça!

Remarque: Si vous supprimez le fichier d'en-tête de pontage de votre projet , assurez-vous d'aller dans les paramètres de construction et supprimez la valeur pour "En -tête de pontage Objective-C " sous "Compilateur Swift - Génération de code".


39

Vous pouvez lire le bel article Swift & Cocoapods . Fondamentalement, nous devons créer un fichier d'en-tête de pontage et y placer tous les en-têtes Objective-C. Et puis nous devons le référencer à partir de nos paramètres de construction. Après cela, nous pouvons utiliser le code Objective-C.

let manager = AFHTTPRequestOperationManager()
manager.GET(
  "http://example.com/resources.json",
  parameters: nil,
  success: { (operation: AFHTTPRequestOperation!,
              responseObject: AnyObject!) in
      println("JSON: " + responseObject.description)
  },
  failure: { (operation: AFHTTPRequestOperation!,
              error: NSError!) in
      println("Error: " + error.localizedDescription)
  })

Consultez également le document d'Apple sur l' utilisation de Swift avec Cocoa et Objective-C .



24

J'aimerais ajouter une chose ici:

Je suis très reconnaissant pour la réponse de @ Logan. Cela aide beaucoup à créer un fichier bridge et des configurations.

Mais après avoir fait toutes ces étapes, je ne reçois toujours pas de classe Objective-C dans Swift.

J'ai utilisé la cocoapodsbibliothèque et l' ai intégrée à mon projet. Ce qui est pod "pop".

Donc, si vous utilisez des pods Objective-C dans Swift, il est possible que vous ne puissiez pas accéder importaux classes ou dans Swift.

La chose simple que vous devez faire est:

  1. Accédez au <YOUR-PROJECT>-Bridging-Headerfichier et
  2. Remplacez l'instruction #import <ObjC_Framework>par@import ObjC_Framework

Par exemple: (Bibliothèque Pop)

Remplacer

#import <pop/POP.h>

avec

@import pop;

À utiliser clang importlorsque #importne fonctionne pas.


Utilisez l'importation clang lorsque #import ne fonctionne pas. quelle? Vous n'avez pas simplement dit que nous devrions utiliser @import?!
Honey

22

Citation de la documentation :

Tout framework Objective-C (ou bibliothèque C) accessible en tant que module peut être importé directement dans Swift. Cela inclut toutes les infrastructures du système Objective-C, telles que Foundation, UIKit et SpriteKit, ainsi que les bibliothèques C communes fournies avec le système. Par exemple, pour importer Foundation, ajoutez simplement cette instruction d'importation en haut du fichier Swift dans lequel vous travaillez:

import Foundation

Cette importation rend toutes les API Foundation — y compris NSDate, NSURL, NSMutableData et toutes leurs méthodes, propriétés et catégories — directement disponibles dans Swift.


12

Juste une note pour quiconque essaie d'ajouter une bibliothèque Objective-C à Swift: vous devez ajouter -ObjC dans les paramètres de construction -> Liaison -> Autres indicateurs de l' éditeur de liens .


Pourquoi? Veuillez ajouter des informations sur ce que fait ce drapeau et pourquoi il devrait être ajouté.
Johan Karlsson

9

Après avoir créé un en-tête de pontage, accédez à Build Setting => Search for "Objective-C Bridging Header".

Juste en dessous, vous trouverez le fichier "" Nom d'en-tête d'interface généré par Objective-C ".

Importez ce fichier dans votre contrôleur de vue.

Exemple: dans mon cas: "Dauble-Swift.h"

description de l'image eEter ici


5

Cliquez sur le menu Nouveau fichier et choisissez Fichier Sélectionner la langue Objectif. À ce moment, il génère automatiquement un fichier "En-tête de pontage Objective-C" qui est utilisé pour définir un nom de classe.

"En-tête de pontage Objective-C" sous "Compilateur Swift - Génération de code".


3
  1. Créez un fichier .h à partir de NewFile -> Source -> fichier d'en-tête
  2. Ensuite, enregistrez le nom du fichier Your_Target_Name-Bridging-Header.h Les gens ici obtiennent une erreur courante en prenant le nom de leur projet, mais il devrait s'agir du nom de la cible du projet si dans le cas où les deux sont différents, ils sont généralement identiques.
  3. Ensuite, dans les paramètres de construction, recherchez l'en -tête de pontage Objective-C indicateur d'en- et mettez l'adresse de votre fichier de pontage nouvellement créé, vous pouvez le faire avec le bouton droit de la souris sur le fichier -> afficher dans le Finder -> faire glisser le fichier dans la zone de texte, puis l'adresse sera être peuplé.
  4. Utilisation de #import Your_Objective-C_file.h
  5. Dans le fichier swift, vous pouvez accéder au fichier ObjC mais en langage swift uniquement.


3

Dans le projet Swift 4.2.1 dans Xcode 10.1, vous pouvez facilement ajouter un fichier Objective-C. Suivez les étapes ci-dessous pour relier le fichier Objective-C au projet Swift.

Étape_01: Créez un nouveau projet Xcode en utilisant le langage Swift:

File> New> Project> objc.

Étape_02: dans le projet Swift, ajoutez un nouveau fichier Objective-C:

File> New> File...> macOS> Objective-C File.

Étape_03: Si vous ajoutez un nouveau fichier Objective-C dans le projet Swift à la toute première fois, Xcode vous demande:

Would you like to configure an Objective-C bridging header?

entrez la description de l'image ici

Étape_04: sélectionnez l'option:

Create Bridging Header.

Étape_05: Un fichier correspondant sera généré avec un nom:

Objc-Bridging-Header.h.

entrez la description de l'image ici

Étape_06: Maintenant, vous devez configurer le chemin du fichier Bridge dans l'en-tête du pont. Dans Project Navigator, cliquez sur projet avec nom objc, puis choisissez:

Build Settings> Objective-C Bridging Header> Objc-Bridging-Header.h.

Étape_07: Glissez-déposez votre Objc-Bridging-Header.hdans cette boîte pour générer un chemin de fichier.

entrez la description de l'image ici

Étape_08: Ouvrez votre Objc-Bridging-Header.hfichier et importez le fichier Objective-C que vous souhaitez utiliser dans votre fichier Swift.

#import "SpecialObjcFile.m"

Voici un contenu de SpecialObjcFile.m:

#import <Foundation/Foundation.h>

@interface Person: NSObject {
@public
    bool busy;
}
@property
    bool busy;
@end

Étape_09: Maintenant dans votre fichier Swift, vous pouvez utiliser une classe Objective-C:

override func viewDidLoad() {
    super.viewDidLoad()
    let myObjcContent = Person()
    print(myObjcContent.busy)
}

entrez la description de l'image ici entrez la description de l'image ici


1

La réponse Logans fonctionne correctement, sauf dans la dernière versionSwift 5 elle donne une erreur de compilation. Voici le correctif pour les personnes qui travaillent sur Swift 5.

Swift 5

import Foundation

class MySwiftObject : NSObject {

    var someProperty: AnyObject = "Some Initializer Val" as AnyObject

    override init() {}

    func someFunction(someArg:AnyObject) -> String {
        let returnVal = "You sent me \(someArg)"
        return returnVal
    }
}

1

Consommateur rapide, producteur Objective-C

  1. Ajouter un en-tête .het des .mfichiers d' implémentation - Fichier de classe Cocoa (Objective-C)
    Par exempleMyFileName

  2. configurer l'en-tête de pontage
    Lorsque vous voyez, Would you like to configure an Objective-C bridging headercliquez sur - Oui

    • <target_name>-Bridging-Header.h sera généré automatiquement
    • Paramètres de construction -> En-tête de pontage Objective-C
  3. Ajouter une classe à Bridging-tête
    En <target_name>-Bridging-Header.hajouter une ligne#import "<MyFileName>.h"

PS Si vous devez ajouter des fichiers Objective-C existants dans le projet Swift, ajoutez Bridging-Header.hau préalable

Consommateur Objective-C, producteur Swift

  1. Ajouter un <MyFileName>.swiftet étendNSObject

  2. Importez des fichiers Swift dans la classe ObjC
    Ajoutez #import "<#YourProjectName#>-Swift.h"dans votre fichier Objective-C

  3. Marquer le code Swift public [@objc et @objcMembers]


0

Apple a fourni un guide officiel dans ce document: comment-appeler-objectif-c-code-de-swift

Voici la partie pertinente:

Pour importer un ensemble de fichiers Objective-C dans le code Swift au sein de la même cible d'application, vous comptez sur un fichier d'en-tête de pontage Objective-C pour exposer ces fichiers à Swift . Xcode propose de créer cet en-tête lorsque vous ajoutez un fichier Swift à une application Objective-C existante, ou un fichier Objective-C à une application Swift existante.

Si vous acceptez, Xcode crée le fichier d'en-tête de pontage avec le fichier que vous créez et le nomme en utilisant le nom de votre module de produit suivi de "-Bridging-Header.h". Vous pouvez également créer vous-même un en-tête de pontage en choisissant Fichier> Nouveau> Fichier> [système d'exploitation]> Source> Fichier d'en-tête

Modifiez l'en-tête de pontage pour exposer votre code Objective-C à votre code Swift:

  1. Dans votre en-tête de pontage Objective-C, importez chaque en-tête Objective-C que vous souhaitez exposer à Swift .
  2. Dans Paramètres de génération, dans Compilateur rapide - Génération de code, assurez-vous que le paramètre de génération En-tête de pontage Objective-C a un chemin d'accès au fichier d'en-tête de pontage. Le chemin doit être relatif à votre projet, de la même manière que votre chemin Info.plist est spécifié dans les paramètres de construction. Dans la plupart des cas, vous n'aurez pas besoin de modifier ce paramètre.

Tous les en-têtes Objective-C publics répertoriés dans l'en-tête de pontage sont visibles par Swift.


0

Approche bidirectionnelle pour utiliser l'objectif-c objectif-c

1

  1. Créer un fichier bridge-header.h dans le projet Xcode
  2. importer le fichier .h dans le fichier Bridge-Header
  3. Définissez le chemin de Bridge-Header dans les paramètres de construction.
  4. Nettoyer le projet

2

  1. Créez des fichiers objective-c dans le projet (il définit automatiquement le chemin dans les paramètres de construction pour vous)
  2. importer le fichier .h dans le fichier Bridge-Header

Maintenant prêt à partir Merci

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.