Llamar a la función Swift desde la clase Objective-C

84

Tengo un antiguo proyecto de Objective-C y quiero llamar a una nueva función y objeto Swift, he creado el archivo " <ProjectName>-Bridging-Header.h" y " <ProjectName>-Swift.h"

Fue fácil para mí llamar a la función de Swift a Objective-C pero tengo un problema para revertir.

Así que he creado una clase simple "System.Swift"

import Foundation

@objc class System : NSObject {

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

ahora he intentado seguir la documentación aquí y dentro del <...>-Swift.harchivo escribí esto

@class System;

@interface System : NSObject

-(void)printSome;

@end

y lo he importado dentro de mi clase Objective-C. En este punto, dentro de mi clase Objective C (actualmente UIViewController) de mi código Objective-C, he intentado llamar al método "printSome":

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

ahora tengo el siguiente error:

Símbolos no definidos para la arquitectura i386: " OBJC_CLASS $ _System", referenciado desde: objc-class-ref en "ObjectiveC_Class_That_Call_Swift_Object" .o ld: símbolo (s) no encontrado para la arquitectura i386 clang: error: el comando del enlazador falló con el código de salida 1 (use -v para ver la invocación)

Eloreden
fuente
Tiene un error de vinculador. ¿Es: (1) Xcode usa el nombre de su módulo de producto, no su nombre de destino, al nombrar el encabezado puente Objective-C y el encabezado generado para su código Swift, o (2) asegúrese de importar los encabezados Objective-C para esos tipos antes de importar el encabezado generado por Swift en el archivo Objective-C .m desde el que desea acceder al código Swift? ¿Tiene: #importar “ProductModuleName-Swift.h” en su código Objective-C?
petert
Sí, he leído la documentación y el nombre de "ProductModelName" es correcto ... Hay un error que dentro de la configuración de compilación no se configuró el modelo del producto ... incluso lo configuré ...
Eloreden
@petert ¿puedes explicar mejor el segundo punto? Escribí todo lo que hice ...
Eloreden
Problema resuelto, agregué un nuevo archivo .h en mi proyecto llamado <ProductModelName> -Swift.h pero esto no es necesario porque el compilador simplemente crea este objeto incluso si no puedo verlo. He eliminado el nuevo archivo que he creado y ahora todo funciona perfectamente. Tnx petert
Eloreden
Puede responder a sus propias preguntas; podría ayudar a otros.
petert

Respuestas:

50

Problema resuelto, anteriormente creé e incluí un nuevo .harchivo en mi clase Objective-C llamado <ProductModuleName>-Swift.hpero, como descubrí más tarde, este paso no es necesario porque el compilador crea el archivo necesario invisible.

Simplemente inclúyalo <ProductModuleName>-Swift.hen su clase y debería funcionar.

Eloreden
fuente
3
¿qué hay de las funciones con parámetros?
Arnlee Vizcayno
3
No puedo acceder a las funciones de Swift con parámetros y un valor de retorno, ni puedo acceder a las funciones de Swift sin parámetros y sin un valor de retorno. No sé por qué. Mi Swift Class es un NSObject, importé el marco Foundation, la clase y las funciones tienen el @objcprefijo. Se -Swift.hha creado automáticamente. Lo que me está dando dolor de cabeza es que puedo llamar a la clase en sí, pero no a ninguna función dentro de ella. ¿Alguien sabe por qué?
David Gölzhäuser
4
buen ejemplo en ericasadun.com/2014/08/21/…
Paul Beusterien
2
Lo es <productModuleName>-.Swift.h(no model).
SwiftArchitect
2
Si su nombre de producto tiene espacios en él, reemplazarlos con guiones bajos, como: #import "My_Project-Swift.h".
EricRobertBrewer
41

es extraño pero funcionará

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

La aplicación generará la interfaz para esta clase en -Swift.h

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

  • (void) notificar para descargar: (NSDictionary *) userInfo;
  • (tipo de instancia) init OBJC_DESIGNATED_INITIALIZER; @fin
Svitlana
fuente
También puede anular el nombre de Obj-C de su clase Swift usando@objc (MyClassName)
nielsbot
12
Para cualquiera que pueda cometer el mismo error tonto que yo. En el paso 2, asegúrese de usar (ProjectName)-Swift.h, NOT (ClassName)-Swift.h !
Hlung
gracias @Svitlana, increíble, funcionó !!! Pero tengo que volver a intentar muchas veces estos pasos, incluido mover mis métodos agregados a otros lugares de la clase.
Scofield Tran
1
3) @class SwiftClassName;me salvó
Mazen Kasser
33

Supongamos que tenemos ProjectName "MyFirstProjectOnSwift" y el nombre de clase rápida "mySwiftClass" y la clase aimC es "MyObjectiveCLass"

Los siguientes pasos son: -

  1. Agregue #import "MyFirstProjectOnSwift-Swift.h" en "MyObjectiveCLass.m"

  2. Agregue @class mySwiftClass en MyObjectiveCLass.h;

  3. Luego en MyObjectiveCLass.m

    mySwiftClass * myClass = [mySwiftClass nuevo]; {Llame así en cualquier método donde desee llamar al método rápido.}

  4. [myClass methodName];

Anubhav Giri
fuente
2
mySwiftClass * myClass = [mySwiftClass nuevo] no funciona para mí >>>>>
Hari Narayanan
@HariNarayanan No debería ser, piense uno en los datos derivados claros y vuelva a abrir su proyecto.
Anubhav Giri
12

Verifique el archivo -Swift.h que tiene la importación en su archivo .m en objetivo-C:

#import <YourProjectName-Swift.h>

Haga clic en esa línea y haga clic con el botón izquierdo - Ir a definición.

Este archivo debe incluirse automáticamente, no manualmente.

Darius Miliauskas
fuente
2

Si aún no ve su clase incluso después de importar <ProductModuleName>-Swift.h.

Asegúrese de que su clase esté subclasificando una clase nativa (por ejemplo UIViewController) o al menos si es solo una clase de utilidad, conviértala en subclase NSObject. Tu clase debería aparecer ahora.

Bryan P
fuente
2

Un pequeño consejo adicional para cualquiera que se encuentre con esta publicación y para quienes las otras respuestas no funcionan: es posible que también deba declarar su clase Swift como "pública".

Ejemplo:

@objc public class MySwiftClass: NSObject {

Kqtr
fuente
0

La forma recomendada de ejecutar código Swift desde Objective-C en proyectos que se están migrando de Obj-C a Swift es utilizando el patrón Bridge / Proxy.

  1. Implementar el puente.

import Foundation

@objc class AnalyticsPropertyBridge: NSObject {

private var analytics: AnalyticsManager = AnalyticsManager()

@objc func refreshProperties() {

    self.analytics.set(AnalyticsProperty.clientType)
}

}

  1. Incluya el módulo de llamada objC en el archivo general (Bridging-Header):

#import "CallerModule.h"

  1. Finalmente, en el archivo .m de la persona que llama, hay dos problemas:

3.a Importar archivo de paraguas:

#import "MyProject-Swift.h"

3.b Llame al puente.

[[AnalyticsPropertyBridge new] refreshProperties];

Beneficios: Su código rápido no se ensuciará con @objc porque el código se llama desde Objc. Con el paso del tiempo, el ObjC se irá reduciendo en tu proyecto y finalmente la novia será eliminada.

Javier Calatrava Llavería
fuente
-1

Un buen artículo aquí por si alguien todavía tiene problemas.

Configuración de la interoperabilidad de Swift y Objective-C

  1. Este artículo analiza en profundidad cómo importar archivos Swift a ObjC, así como archivos Objc a Swift.
  2. También aborda un problema que generalmente se enfrenta cuando el nombre del proyecto tiene espacio.
  3. También trata sobre el indicador "Nombre del módulo de producto".
Tridente
fuente
Si bien esto puede responder teóricamente a la pregunta, sería preferible incluir aquí las partes esenciales de la respuesta y proporcionar el enlace como referencia.
Arghya Sadhu