Importieren eines Swift-Protokolls in die Objective-C-Klasse


115

Ich versuche, ein Swift-Protokoll mit dem Namen AnalyticProtocolin eine Objective-C-Klasse mit dem Namen zu importieren AnalyticFactory.

protocol AnalyticProtocol
{

}

Ich gehe von einem vorhandenen Objective-C-Projekt aus (ich habe mit xCode kein neues Swift-Projekt erstellt und nicht herausgefunden, wie ich mein Objective-C-Projekt in xCode 6 als Swift-Projekt konfigurieren kann ).

In meine Swift-Datei habe ich die .hDatei mit dem Namen aufgenommen, MyProjectName-Swift.haber der Compiler hat mir einen Fehler zurückgegeben, der mir mitteilt, dass sie nicht vorhanden ist . Also habe ich eine .hDatei mit dem Namen erstellt, MyProjectName-Swift.hdie tatsächlich leer ist (ich weiß nicht, was ich einfügen soll).

In der Apple-Dokumentation heißt es, dass ich meine .hbenannte Datei MyProjectName-Swift.hin meine .mDatei aufnehmen muss. Aber ich muss es nicht in meine .mDatei aufnehmen, sondern in meine .h. Kann das problematisch sein?

Beim Kompilieren wird der folgende Fehler angezeigt :: 0: Fehler: xxxAnalyticFactory.h: 39: Protokolldeklaration für 'AnalyticProtocol' kann nicht gefunden werden

Und der belastete Code:

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

Ich glaube, ich verstehe nicht gut, wie ich ein Swift-Protokoll in eine Objective-C-Klasse importieren kann.

Hat jemand einen Fehler in dem gesehen, was ich tue?


Schauen Sie sich das Video zur Integration von Swift mit Objective-C von WWDC 2014 an. Gegen 30:40 Uhr im Video wird beschrieben, wie Sie auf Swift-Protokolle in Objective-C-Klassen zugreifen.
Jamie Forrest

Antworten:


224

Sie müssen das @objcAttribut wie folgt zu Ihrem Swift-Protokoll hinzufügen :

@objc protocol AnalyticProtocol {

}

25
Vielen Dank für Ihre Antwort, aber das Problem besteht weiterhin.
Jean Lebrument

Könnten Sie vielleicht ein Beispielprojekt veröffentlichen, das das Problem reproduziert?
Jamie Forrest

Das Hinzufügen von @objc half mir beim Importieren von Swift-Klassen in Obj-C
serg

19
@objc funktioniert nicht immer. Wenn es einem Protokoll entspricht, funktioniert es manchmal nicht, wenn das Protokoll @interfacein der .hDatei hinzugefügt wird . Sie können das Protokoll jedoch zu dem privaten @interfacein der .mDatei hinzufügen und es behebt Probleme (zumindest gelegentlich für mich). Also über Ihre @implementationhaben @interface MyController() <AnalyticProtocol>.
Adam

1
Manchmal beschwert sich Xcode 8 während der Bearbeitung, aber wenn Sie es tatsächlich erstellen und diese Antwort zusammen mit den Kommentaren befolgen, wird der Fehler behoben.
Roger Pingleton

76

Es ist nicht möglich, den von Xcode generierten Swift-Header in objC-Header-Dateien zu importieren.

Da Sie also Swift-Code in einer objC-Header-Datei verwenden möchten, müssen Sie die Klassen und Protokolle, die Sie in der objC-Header-Datei verwenden möchten, wie folgt "weiter deklarieren":

@protocol AnalyticProtocol;

Sie können das Protokoll jetzt in Ihrer objC-Klassendeklaration verwenden:

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

In Ihrer Implementierungsdatei (die objC .m-Datei) können Sie die von Xcode generierte Swift-Headerdatei ("ProductModuleName-Swift.h") importieren, und die richtige Implementierung AnalyticProtocolist dem Compiler jetzt bekannt.

Dies wird auch im Abschnitt "Verwenden von Swift von Objective-C" in den Apple Docs beschrieben

Beachten Sie, dass XCode eine Warnung in der objC-Header-Datei ausgibt, wenn Sie das vorwärts deklarierte Protokoll verwenden ("Protokolldefinition für 'AnalyticProtocol' kann nicht gefunden werden), dies kann jedoch ignoriert werden - die Implementierung wird zur Kompilierungszeit gefunden.


19
Warum zeigt Xcode die Warnung für fehlendes Protokoll an, wenn es kompiliert wird und ordnungsgemäß funktioniert? Gibt es eine Möglichkeit, die Warnung zu entfernen?
Oren

Es ist jedoch immer noch nicht möglich, die Protokollmethoden für diese Klasse aufzurufen. Es wird den Fehler gebenNo visible @interface for <ClassName> declares the selector <protocolMethodName>
Elsa

Es wird die folgende Warnung
ausgegeben

51

Für alle, die lediglich ein Protokoll benötigen - Sie können dies in zwei Schritten tun, ohne Warnungen oder Fehler zu generieren:

  1. Fügen Sie in Ihrer .swiftDatei @objcvor dem Protokollnamen Folgendes hinzu:

    @objc protocol AnalyticProtocol {
    
    }
  2. .mImportieren Sie in Ihrer Datei den generierten Swift-Header und übernehmen Sie das Protokoll in eine private Kategorie. (Die Header-Datei wird automatisch benannt):

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

Dies ist der von Apple empfohlene Ansatz. Weitere Informationen zum Mischen und Anpassen von Objective-C und Swift finden Sie hier: https://developer.apple.com/library/content/documentation/Swift/Conceptual/BuildingCocoaApps/MixandMatch.html


1
Ich bekomme immer noch eine Warnung, mit oder ohne Vorwärtserklärung. Ich verwende das Protokoll in einer Erweiterung.
Cristi Băluță

Kann nicht importiert werden #import "AnalyticProtocol-Swift.h". Sieht so aus, als würde WhateverProtocol-Swift.h nicht automatisch generiert, wie Sie sagten.
Hlung

2
Das hat bei mir funktioniert; Keine anderen Vorschläge oder Antworten auf dieser Seite haben funktioniert. Ich bin auf Swift 4.
Poulsbo

1
Dies war die einzige Möglichkeit, die Warnung zu entfernen (obwohl sie funktioniert, wenn sich die Protokolle in der Header-Datei befinden)
David P

1
Der gleiche Link ist über WebArchive verfügbar: web.archive.org/web/20170310053717/https://developer.apple.com/…
Richard Topchii

3

Wenn Sie ein Framework erstellen, wird der erforderliche Import durchgeführt

#import "ProductModuleName-Swift.h"

Änderungen an:

#import <ProductModuleName/ProductModuleName-Swift.h>

In diesem Fall müssen Sie auch die rasche Protokoll machen Öffentlichkeit :

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

3

Wir können schnelle Protokolle in Ziel C mit wenigen Änderungen am Code verwenden. Mit den von @objc deklarierten Protokollen können Sie außerdem optionale und erforderliche Methoden ohne Standardimplementierungen verwenden. Es kommt mit Vor- und Nachteilen.

Wir könnten den Protokollnamen bei Verwendung in Ziel C tatsächlich in einen aussagekräftigeren Namen umbenennen. Ich verwende "@objc (alias_name)".

Hier ist der Code: Lassen Sie uns ein schnelles Protokoll mit dem Attribut @objc und dem Aliasnamen verwenden, das im ObjC-Code verwendet werden soll.

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

Lassen Sie uns nun farword unser Protokoll in der .h-Datei deklarieren

@protocol ObjTableViewReloadable;

Sie können dieses Protokoll jetzt in der M-Datei anpassen und die Implementierung der erforderlichen Methoden hinzufügen.

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

Vielen Dank für die Veröffentlichung. Ich betrachte Legacy-Code, der älter als Dreck ist, und wenn dieser Ansatz funktioniert, erspart er mir eine Menge Schmerzen. :)
Adrian
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.