Chiama la funzione Swift dalla classe Objective-C


84

Ho un vecchio progetto Objective-C e voglio chiamare una nuova funzione e oggetto Swift, devo creare il file " <ProjectName>-Bridging-Header.h" e " <ProjectName>-Swift.h"

è stato facile per me chiamare la funzione da Swift a Objective-C ma ho un problema per il contrario.

Quindi ho creato una semplice classe "System.Swift"

import Foundation

@objc class System : NSObject {

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

ora devo provare a seguire la documentazione qui e all'interno del <...>-Swift.hfile ho scritto questo

@class System;

@interface System : NSObject

-(void)printSome;

@end

e l'ho importato nella mia classe Objective-C. A questo punto all'interno della mia classe Objective C (attualmente UIViewController) del mio codice Objective-C provo a chiamare il metodo "printSome":

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

ora ho il seguente errore:

Simboli indefiniti per l'architettura i386: " OBJC_CLASS $ _System ", referenziato da: objc-class-ref in "ObjectiveC_Class_That_Call_Swift_Object" .o ld: symbol (s) not found for architecture i386 clang: error: linker command failed with exit code 1 (use -v per vedere l'invocazione)


Hai un errore del linker. È: (1) Xcode utilizza il nome del modulo del prodotto, non il nome di destinazione, quando nomina l'intestazione bridge Objective-C e l'intestazione generata per il tuo codice Swift, oppure (2) assicurati di importare le intestazioni Objective-C per quelle prima di importare l'intestazione generata da Swift nel file Objective-C .m da cui desideri accedere al codice Swift? Hai: #import "ProductModuleName-Swift.h" nel tuo codice Objective-C?
petert

Sì, ho letto la documentazione e il nome di "ProductModelName" è attuale ... C'è un bug che all'interno del Build Setting il modello del prodotto non era impostato ... l'ho persino impostato ...
Eloreden

@petert puoi spiegare meglio il secondo punto? Ho scritto tutto quello che ho fatto ...
Eloreden

Problema risolto, ho aggiunto un nuovo file .h nel mio progetto chiamata <ProductModelName> -Swift.h ma questo non è necessario perché il compilatore crea questo oggetto anche se non riesco a vederlo. Ho eliminato il nuovo file che ho creato e ora tutto funziona perfettamente. Tnx petert
Eloreden

Puoi rispondere alle tue domande - potrebbe aiutare gli altri.
petert

Risposte:


52

Problema risolto, ho precedentemente creato e incluso un nuovo .hfile nella mia classe Objective-C denominato <ProductModuleName>-Swift.hma, come ho scoperto in seguito, questo passaggio non è necessario perché il compilatore crea il file necessario invisibile.

Includilo semplicemente <ProductModuleName>-Swift.hnella tua classe e dovrebbe funzionare.


3
che ne dici di funzioni con parametri?
Arnlee Vizcayno

3
Non sono in grado di accedere alle funzioni Swift con parametri e un valore di ritorno, né sono in grado di accedere alle funzioni Swift senza parametri e senza un valore di ritorno. Non so perché La mia Swift Class è un NSObject, ho importato il framework Foundation, la classe e le funzioni hanno il @objcprefisso. Il -Swift.hè stato creato automaticamente. La cosa che mi fa venire il mal di testa è che posso chiamare la classe stessa ma non alcuna funzione al suo interno. Qualcuno sa perché?
David Gölzhäuser


2
Lo è <productModuleName>-.Swift.h(non model).
SwiftArchitect

2
Se il nome del prodotto ha qualunque spazi, sostituirli con sottolineature, come: #import "My_Project-Swift.h".
EricRobertBrewer

41

è strano ma funzionerà

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

L'app genererà l'interfaccia per questa classe in -Swift.h

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

  • (void) notifyForDownloading: (NSDictionary *) userInfo;
  • (tipo di istanza) init OBJC_DESIGNATED_INITIALIZER; @fine

Puoi anche sovrascrivere il nome Obj-C della tua classe Swift usando@objc (MyClassName)
nielsbot

12
Per chiunque possa fare lo stesso stupido errore di me. Nel passaggio 2, assicurati di utilizzare (ProjectName)-Swift.h, NON (ClassName)-Swift.h !
Hlung

grazie @Svitlana, incredibile, ha funzionato !!! Ma devo riprovare molte volte questi passaggi, incluso lo spostamento dei metodi aggiunti in altri punti della classe.
Scofield Tran

1
3) @class SwiftClassName;mi ha salvato
Mazen Kasser

33

Supponiamo di avere ProjectName "MyFirstProjectOnSwift" e il nome della classe swift "mySwiftClass" e la classe ObjectiveC è "MyObjectiveCLass"

I passaggi seguenti sono: -

  1. Aggiungi #import "MyFirstProjectOnSwift-Swift.h" in "MyObjectiveCLass.m"

  2. Aggiungi @class mySwiftClass in MyObjectiveCLass.h;

  3. Quindi in MyObjectiveCLass.m

    mySwiftClass * myClass = [mySwiftClass new]; {Call Like This in any method ovunque tu voglia chiamare il metodo swift.}

  4. [myClass methodName];


2
mySwiftClass * myClass = [mySwiftClass new] non funziona per me >>>>>
Hari Narayanan

@HariNarayanan Non dovrebbe essere, pensate che i dati derivati ​​chiari e riaprite il vostro progetto.
Anubhav Giri

12

Controlla il file -Swift.h che ha l'importazione sul tuo file .m in Object-C:

#import <YourProjectName-Swift.h>

Fare clic su quella linea e fare clic con il pulsante sinistro del mouse su Salta alla definizione.

Questo file dovrebbe essere incluso automaticamente, non manualmente.


2

Se continui a non vedere la tua classe anche dopo l'importazione <ProductModuleName>-Swift.h.

Assicurati che la tua classe stia sottoclasse una classe nativa (ad esempio UIViewController) o almeno se è solo una classe di utilità, rendila sottoclasse NSObject. La tua classe dovrebbe ora essere visualizzata.


2

Piccolo suggerimento aggiuntivo per chi si imbatte in questo post e per chi le altre risposte non funzionano: potresti anche dover dichiarare la tua classe Swift "pubblica".

Esempio:

@objc public class MySwiftClass: NSObject {


0

Il modo consigliato per eseguire codice Swift da Objective-C su progetti che vengono migrati da Obj-C a Swift è utilizzare il pattern Bridge / Proxy.

  1. Implementa il ponte.

import Foundation

@objc class AnalyticsPropertyBridge: NSObject {

private var analytics: AnalyticsManager = AnalyticsManager()

@objc func refreshProperties() {

    self.analytics.set(AnalyticsProperty.clientType)
}

}

  1. Includere il modulo chiamante objC nel file ombrello (Bridging-Header):

#import "CallerModule.h"

  1. Infine nel file .m del chiamante, due problemi:

3.a Importa file ombrello:

#import "MyProject-Swift.h"

3.b Chiama il ponte.

[[AnalyticsPropertyBridge new] refreshProperties];

Vantaggi: il tuo codice swift non si sporcherà con @objc perché il codice viene chiamato da Objc. Col passare del tempo, l'ObjC verrà ridotto nel tuo progetto e alla fine la sposa verrà rimossa.


-1

Un buon articolo qui se qualcuno ha ancora problemi.

Impostazione dell'interoperabilità Swift e Objective-C

  1. Questo articolo spiega in modo approfondito come importare file Swift in ObjC e file Objc in Swift.
  2. Risolve anche un problema che generalmente si verifica quando il nome del progetto contiene spazio.
  3. Discute anche sul flag "Product Module Name".

Sebbene questo possa teoricamente rispondere alla domanda, sarebbe preferibile includere qui le parti essenziali della risposta e fornire il collegamento per riferimento.
Arghya Sadhu
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.