Rufen Sie die Swift-Funktion aus der Objective-C-Klasse auf

83

Ich habe ein altes Objective-C-Projekt und möchte eine neue Swift-Funktion und ein neues Swift-Objekt aufrufen. Ich habe die Dateien " <ProjectName>-Bridging-Header.h" und " <ProjectName>-Swift.h" erstellt.

Es war einfach für mich, die Funktion von Swift nach Objective-C aufzurufen, aber ich habe ein Problem mit der Umkehrung.

Also habe ich eine einfache Klasse "System.Swift" erstellt

import Foundation

@objc class System : NSObject {

    @objc func printSome() {
        println("Print line System");
    }
    
}

Jetzt habe ich versucht, der Dokumentation hier zu folgen und in der <...>-Swift.hDatei habe ich dies geschrieben

@class System;

@interface System : NSObject

-(void)printSome;

@end

und ich habe es in meine Objective-C-Klasse importiert. An diesem Punkt in meiner Objective C-Klasse (derzeit UIViewController) meines Objective-C-Codes habe ich versucht, die "printSome" -Methode aufzurufen:

- (void)viewDidLoad
{
    [super viewDidLoad];
    System * sis = [[System alloc] init];
    [sis printSome];
    //any additional setup after loading the view from its nib.
}

Jetzt habe ich folgenden Fehler:

Undefinierte Symbole für Architektur i386: " OBJC_CLASS $ _System", referenziert von: objc-class-ref in "ObjectiveC_Class_That_Call_Swift_Object" -v um Aufruf zu sehen)

Eloreden
quelle
Sie haben einen Linkerfehler. Ist es: (1) Xcode verwendet Ihren Produktmodulnamen - nicht Ihren Zielnamen -, wenn Sie den Objective-C-Bridging-Header und den generierten Header für Ihren Swift-Code benennen, oder (2) stellen Sie sicher, dass Sie die Objective-C-Header für diese importieren Typen vor dem Importieren des von Swift generierten Headers in die Objective-C .m-Datei, von der aus Sie auf den Swift-Code zugreifen möchten? Haben Sie: #import "ProductModuleName-Swift.h" in Ihrem Objective-C-Code?
Petert
Ja, ich habe die Dokumentation gelesen und der Name von "ProductModelName" ist korrekt ... Es gibt einen Fehler, dass in der Build-Einstellung das Produktmodell nicht festgelegt wurde ... ich habe es sogar festgelegt ...
Eloreden
@petert kannst du den zweiten Punkt besser erklären? Ich schrieb alles, was ich tat ...
Eloreden
Problem behoben, ich habe eine neue .h-Datei in meinem Projektaufruf <ProductModelName> -Swift.h hinzugefügt, aber dies ist nicht erforderlich, da der Compiler dieses Objekt nur erstellt, auch wenn ich es nicht sehen kann. Ich habe die neue Datei, die ich erstellt habe, gelöscht und jetzt laufen alle perfekt. Tnx petert
Eloreden
Sie können Ihre eigenen Fragen beantworten - es könnte anderen helfen.
Petert

Antworten:

50

Problem behoben, ich habe zuvor eine neue .hDatei mit dem Namen " Objective-C" erstellt und in meine Objective-C- Klasse aufgenommen <ProductModuleName>-Swift.h. Wie ich später feststellte, ist dieser Schritt nicht erforderlich, da der Compiler die erforderliche Datei unsichtbar erstellt.

Einfach <ProductModuleName>-Swift.hin deine Klasse aufnehmen und es sollte funktionieren.

Eloreden
quelle
3
Wie wäre es mit Funktionen mit Parametern?
Arnlee Vizcayno
3
Ich kann weder mit Parametern und einem Rückgabewert auf Swift-Funktionen zugreifen, noch kann ich ohne Parameter und ohne Rückgabewert auf Swift-Funktionen zugreifen. Ich weiß nicht warum. Meine Swift-Klasse ist ein NSObject. Ich habe das Foundation-Framework importiert. Die Klasse und die Funktionen haben das @objcPräfix. Das -Swift.hwurde automatisch erstellt. Das, was mir Kopfschmerzen bereitet, ist, dass ich die Klasse selbst aufrufen kann, aber keine Funktion darin. Weiß jemand warum?
David Gölzhäuser
4
gutes Beispiel bei ericasadun.com/2014/08/21/…
Paul Beusterien
2
Es ist <productModuleName>-.Swift.h(nicht model).
SwiftArchitect
2
Wenn Ihr Produktname Leerzeichen enthält, ersetzen Sie diese durch Unterstriche wie : #import "My_Project-Swift.h".
EricRobertBrewer
39

Es ist seltsam, aber es wird funktionieren

1) Add @objc  to  Swift class

2) Add in .m 
    #import "(ProjectName)-Swift.h"

3) Call from .h
    @class SwiftClass;

4)On SwiftClass 
   click "Command" + Left Click (Apple Documantation)

5) To see "-Swift.h" -> click "Command" + Left Click

Die App generiert die Schnittstelle für diese Klasse in -Swift.h

Beispiel: SWIFT_CLASS ("_ TtC10Project17220PLHelper") @interface PLHelper

  • (void) notifyForDownloading: (NSDictionary *) userInfo;
  • (Instanztyp) init OBJC_DESIGNATED_INITIALIZER; @Ende
Svitlana
quelle
Sie können den Obj-C-Namen Ihrer Swift-Klasse auch mit@objc (MyClassName)
nielsbot
12
Für jeden, der den gleichen dummen Fehler wie ich machen kann. In Schritt 2 stellen Sie sicher , verwenden Sie (ProjectName)-Swift.h, NICHT (ClassName)-Swift.h !
Hlung
danke @Svitlana, unglaublich, es hat funktioniert !!! Aber ich muss diese Schritte viele Male wiederholen, einschließlich der Verlagerung meiner hinzugefügten Methoden an andere Stellen in der Klasse.
Scofield Tran
1
3) @class SwiftClassName;hat mich gerettet
Mazen Kasser
33

Angenommen, wir haben den Projektnamen "MyFirstProjectOnSwift" und den schnellen Klassennamen "mySwiftClass". Die ObjectiveC-Klasse lautet "MyObjectiveCLass".

Folgende Schritte sind: -

  1. Fügen Sie #import "MyFirstProjectOnSwift-Swift.h" in "MyObjectiveCLass.m" hinzu.

  2. Fügen Sie @class mySwiftClass in MyObjectiveCLass.h hinzu;

  3. Dann in MyObjectiveCLass.m

    mySwiftClass * myClass = [mySwiftClass new]; {Call Like This in jeder Methode, wo immer Sie die Swift-Methode aufrufen möchten.}

  4. [myClass methodName];

Anubhav Giri
quelle
2
mySwiftClass * myClass = [mySwiftClass neu] es funktioniert nicht für mich >>>>>
Hari Narayanan
@ HariNarayanan Es sollte nicht sein, denken Sie klar abgeleitete Daten und öffnen Sie Ihr Projekt erneut.
Anubhav Giri
12

Überprüfen Sie die Datei -Swift.h, die den Import in Ihre .m-Datei in Ziel-C enthält:

#import <YourProjectName-Swift.h>

Klicken Sie auf diese Zeile und klicken Sie mit der linken Maustaste - Zur Definition springen.

Diese Datei sollte automatisch und nicht manuell aufgenommen werden.

Darius Miliauskas
quelle
2

Wenn Sie Ihre Klasse auch nach dem Importieren immer noch nicht sehen <ProductModuleName>-Swift.h.

Stellen Sie sicher, dass Ihre Klasse eine native Klasse (z. B. UIViewController) unterklassifiziert, oder machen Sie sie zumindest zu einer Unterklasse, wenn es sich nur um eine Utility-Klasse handelt NSObject. Ihre Klasse sollte jetzt zeigen.

Bryan P.
quelle
0

Kleiner zusätzlicher Tipp für alle, die über diesen Beitrag stolpern und für die die anderen Antworten nicht funktionieren: Möglicherweise müssen Sie Ihre Swift-Klasse auch als "öffentlich" deklarieren.

Beispiel:

@objc public class MySwiftClass: NSObject {

Kqtr
quelle
0

Die empfohlene Methode zum Ausführen von Swift-Code von Objective-C in Projekten, die von Obj-C nach Swift migriert werden, ist die Verwendung des Bridge / Proxy-Musters.

  1. Implementieren Sie die Brücke.

import Foundation

@objc class AnalyticsPropertyBridge: NSObject {

private var analytics: AnalyticsManager = AnalyticsManager()

@objc func refreshProperties() {

    self.analytics.set(AnalyticsProperty.clientType)
}

}

  1. Fügen Sie das objC-Aufrufermodul in die Umbrella-Datei (Bridging-Header) ein:

#import "CallerModule.h"

  1. Schließlich in der .m-Datei des Anrufers zwei Probleme:

3.a Umbrella-Datei importieren:

#import "MyProject-Swift.h"

3.b Rufen Sie die Brücke an.

[[AnalyticsPropertyBridge new] refreshProperties];

Vorteile: Ihr schneller Code wird mit @objc nicht schmutzig, da Code von Objc aufgerufen wird. Mit der Zeit wird der ObjC in Ihrem Projekt reduziert und schließlich wird die Braut entfernt.

Javier Calatrava Llavería
quelle
-1

Ein guter Artikel hier draußen, wenn jemand noch Probleme hat.

Einrichten der schnellen und Objective-C-Interoperabilität

  1. Dieser Artikel beschreibt ausführlich, wie Swift-Dateien in ObjC sowie Objc-Dateien in Swift importiert werden.
  2. Es wird auch ein Problem behoben, das im Allgemeinen auftritt, wenn der Projektname Platz enthält.
  3. Außerdem wird das Flag "Name des Produktmoduls" erläutert.
Dreizack
quelle
Während dies theoretisch die Frage beantworten kann, wäre es vorzuziehen , die wesentlichen Teile der Antwort hier aufzunehmen und den Link als Referenz bereitzustellen.
Arghya Sadhu