Importer un protocole Swift en classe Objective-C


116

J'essaie d'importer un protocole Swift nommé AnalyticProtocoldans une classe Objective-C nommée AnalyticFactory.

protocol AnalyticProtocol
{

}

Je pars d'un projet Objective-C existant (je n'ai pas créé de nouveau projet Swift avec xCode et je n'ai pas trouvé comment configurer mon projet Objective-C pour être un projet Swift dans xCode 6 ).

Dans mon fichier Swift, j'ai inclus le .hfichier nommé MyProjectName-Swift.hmais le compilateur m'a renvoyé une erreur m'indiquant qu'il n'existe pas . Donc, j'ai créé un .hfichier nommé MyProjectName-Swift.hqui est en fait vide (je ne sais pas ce que je dois mettre à l'intérieur).

Dans la documentation Apple, ils ont dit que je devais inclure mon .hfichier nommé MyProjectName-Swift.hdans mon .mfichier. Mais je dois l'inclure non pas dans mon .mfichier mais dans mon fichier .h. Cela peut-il être problématique?

Lorsque j'essaie de compiler, j'ai cette erreur:: 0: erreur: xxxAnalyticFactory.h: 39: impossible de trouver la déclaration de protocole pour 'AnalyticProtocol'

Et le code incriminé:

@interface AnalyticFactory : NSObject
{
    Class<AnalyticProtocol> _analyticProtocolClass; // The type of the analytic class currently used.
}

Je pense que je ne comprends pas bien comment importer un protocole Swift dans une classe Objective-C.

Quelqu'un voit-il une erreur dans ce que je fais?


Regardez la vidéo Intégration de Swift avec Objective-C de la WWDC 2014. Vers 30 h 40 dans la vidéo, ils décrivent comment accéder aux protocoles Swift dans les classes Objective-C.
Jamie Forrest

Réponses:


224

Vous devez ajouter l' @objcattribut à votre protocole Swift comme suit:

@objc protocol AnalyticProtocol {

}

25
Merci pour votre réponse mais le problème persiste.
Jean Lebrument

Pourriez-vous publier un exemple de projet qui reproduit le problème?
Jamie Forrest

L'ajout de @objc m'a aidé à importer des classes Swift dans Obj-C
serg

19
@objc ne fonctionne pas toujours. Lorsque vous vous conformez à un protocole, cela ne fonctionne pas toujours lors de l'ajout du protocole @interfacedans le .hfichier. cependant, vous pouvez ajouter le protocole au privé @interfacedans le .mfichier et il corrige les choses (du moins il l'a pour moi à l'occasion). Donc au-dessus de votre @implementationavoir @interface MyController() <AnalyticProtocol>.
Adam

1
Parfois, Xcode 8 se plaindra pendant que vous éditez, mais lorsque vous le construisez, en suivant cette réponse avec les commentaires, l'erreur disparaîtra.
Roger Pingleton

77

Il n'est pas possible d'importer l'en-tête Swift généré par Xcode dans les fichiers d'en-tête objC.

Donc, puisque vous souhaitez utiliser du code Swift dans un fichier d'en-tête objC, vous devrez "déclarer en avant" les classes et protocoles que vous souhaitez utiliser dans le fichier d'en-tête objC, comme ceci:

@protocol AnalyticProtocol;

Vous pouvez maintenant utiliser le protocole dans votre déclaration de classe objC:

@interface AnalyticFactory : NSObject
{
    Class<AnalyticProtocol> _analyticProtocolClass; // The type of the analytic class currently used.
}

Dans votre fichier d'implémentation (le fichier objC .m), vous pouvez importer le fichier d'en-tête Swift généré par Xcode ("ProductModuleName-Swift.h") et l'implémentation correcte AnalyticProtocolsera désormais connue du compilateur.

Ceci est également décrit dans la section «Utilisation de Swift à partir d'Objective-C» dans la documentation Apple

Notez que XCode donnera un avertissement dans le fichier d'en-tête objC lorsque vous utilisez le protocole déclaré avant ("Impossible de trouver la définition de protocole pour 'AnalyticProtocol'), mais cela peut être ignoré - l'implémentation sera trouvée au moment de la compilation.


19
Pourquoi Xcode affiche-t-il l'avertissement de protocole manquant lorsqu'il se compile et fonctionne correctement? Un moyen de supprimer l'avertissement?
Oren

Cependant, il n'est toujours pas possible d'appeler les méthodes de protocole sur cette classe. Il donnera l'erreurNo visible @interface for <ClassName> declares the selector <protocolMethodName>
Elsa

il produit l'avertissement suivant: "Impossible de trouver la définition de protocole pour xxxx"
JAHelia

51

Pour quiconque a simplement besoin d'adopter un protocole - vous pouvez le faire en deux étapes, sans générer d'avertissements ou d'erreurs:

  1. Dans votre .swiftfichier, ajoutez @objcavant le nom du protocole:

    @objc protocol AnalyticProtocol {
    
    }
  2. Dans votre .mfichier, importez l'en-tête Swift généré et adoptez le protocole dans une catégorie privée. (Le fichier d'en-tête est nommé automatiquement):

    #import "ProductModuleName-Swift.h"
    
    @interface AnalyticFactory () <AnalyticProtocol>
    
    @end

C'est l'approche recommandée par Apple. Vous pouvez en savoir plus sur le mélange et la correspondance entre Objective-C et Swift ici: https://developer.apple.com/library/content/documentation/Swift/Conceptual/BuildingCocoaApps/MixandMatch.html


1
Je reçois toujours un avertissement, avec ou sans déclaration préalable. J'utilise le protocole dans une extension.
Cristi Băluță

Impossible d'importer #import "AnalyticProtocol-Swift.h". On dirait que WhateverProtocol-Swift.h n'est pas généré automatiquement comme vous l'avez dit.
Hlung

2
Cela a fonctionné pour moi; aucune autre suggestion ou réponse sur cette page n'a fonctionné. Je suis sur Swift 4.
Poulsbo

1
C'était le seul moyen de supprimer l'avertissement (même si cela fonctionne lorsque les protocoles sont dans le fichier d'en-tête)
David P

1
Le même lien est disponible via WebArchive: web.archive.org/web/20170310053717/https
Richard Topchii

3

Si vous créez un framework, l'importation requise

#import "ProductModuleName-Swift.h"

change pour:

#import <ProductModuleName/ProductModuleName-Swift.h>

Dans ce cas, vous devez également rendre public le protocole swift :

@objc public protocol AnalyticProtocol {
  func something();
}

3

Nous pouvons utiliser des protocoles rapides en Objective C avec quelques modifications du code. De plus, les protocoles déclarés @objc vous permettent d'avoir des méthodes facultatives et obligatoires sans implémentations par défaut. Il comporte des avantages et des inconvénients.

Nous pourrions en fait renommer le nom du protocole en un nom plus descriptif lors de l'utilisation en Objective C. J'utilise "@objc (alias_name)".

Voici le code, ayons un protocole rapide avec l'attribut @objc et le nom d'alias à utiliser dans le code ObjC.

@objc(ObjTableViewReloadable) protocol TableViewReloadable: class {
   func reloadRow(at index: IndexPath)
   func reloadSection(at index: Int)
   func reloadTable()
}

Laissons maintenant farword déclarer notre protocole dans un fichier .h

@protocol ObjTableViewReloadable;

Vous pouvez maintenant vous conformer à ce protocole dans le fichier .m et ajouter l'implémentation des méthodes requises.

#import "MyApp-Swift.h"
@interface MyObjcViewController () <ObjTableViewReloadable>

Merci d'avoir posté ceci. Je regarde du code hérité qui est plus ancien que la saleté et si cette approche fonctionne, cela me sauvera beaucoup de douleur. :)
Adrian le
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.