No se pueden usar clases Swift dentro de Objective-C

Intento integrar el código Swift en mi aplicación. Mi aplicación está escrita en Objective-C y agregué una clase Swift . He hecho todo lo que se describe aquí . Pero mi problema es que Xcode no ha creado el archivo -Swift.h , solo los encabezados puente. Así que lo creé, pero en realidad está vacío. Puedo usar todas mis clases ObjC en Swift, pero no puedo hacerlo al revés. @objc mi clase rápida con @objc pero no ayudó. ¿Qué puedo hacer ahora?

EDITAR: Apple dice: “Cuando importa código Swift en Objective-C, confía en un archivo de encabezado Xcode-generated para exponer esos archivos a Objective-C. […] El nombre de este encabezado es el nombre de su módulo de producto seguido agregando “-Swift.h”. ”

Ahora cuando quiero importar ese archivo, me da un error:

  //MainMenu.m #import "myProjectModule-Swift.h" //Error: 'myProjectModule-Swift.h' file not found @implementation MainMenu 

Aquí está mi archivo FBManager.swift:

 @objc class FBManager: NSObject { var descr = "FBManager class" init() { super.init() } func desc(){ println(descr) } func getSharedGameState() -> GameState{ return GameState.sharedGameState() //OK! GameState is written in Objective-C and no error here } } 

Pasé aproximadamente 4 horas intentando habilitar Swift en mi proyecto Xcode Objective-C. Mi myproject-Swift.hmyproject-Swift.h ” se creó con éxito, pero mi Xcode no vio mis Swift-classes . Entonces, decidí crear un nuevo proyecto basado en Xcode Objc y finalmente encontré la respuesta correcta. Espero que esta publicación ayude a alguien 🙂

Integración Swift paso a paso para el proyecto Xcode Objc:

  1. Crea un nuevo archivo *.swift (en Xcode) o *.swift usando Finder
  2. Cree un Objective-C bridging header cuando Xcode le pregunte sobre eso
  3. Implementa tu clase Swift con el atributo @objc :

     import Foundation class Foo { //.. } 
  4. Abra Configuraciones de comstackción y verifique esos parámetros:

    • Define el Módulo: YES

      Copiar y pegar el nombre del parámetro en una barra de búsqueda

    • Nombre del módulo de producto: myproject

      Asegúrese de que su Nombre de Módulo de Producto no contenga ningún carácter especial

    • Instalar el encabezado de compatibilidad de Objective-C: YES

      Una vez que haya agregado el archivo *.swift al proyecto, esta propiedad aparecerá en Configuración de comstackción.

    • Cabecera de la interfaz generada por Objective-C: myproject-Swift.h

      Este encabezado es generado automáticamente por Xcode

    • Objective-C Bridging Encabezado: $(SRCROOT)/myproject-Bridging-Header.h
  5. Encabezado de la interfaz de Swift en su archivo * .m

     #import "myproject-Swift.h" 

    No preste atención a los errores y advertencias.

  6. Limpia y reconstruye tu proyecto de Xcode
  7. ¡Lucro!

No crees el archivo de encabezado tú mismo. Elimina el que creaste.

Asegúrese de que sus clases Swift estén etiquetadas con @objc o hereden de una clase derivada (directa o indirectamente) de NSObject .

Xcode no generará el archivo si tiene errores de comstackción en su proyecto: asegúrese de que su proyecto se genere de forma limpia.

Permita que Xcode haga su trabajo, no agregue / cree el encabezado Swift manualmente. Simplemente agregue @objc antes de su clase Swift ex.

 @objc class YourSwiftClassName: UIViewController 

En la configuración de su proyecto, busque los indicadores siguientes y cámbielo a SÍ (Proyecto y Destino)

 Defines Module : YES Always Embed Swift Standard Libraries : YES Install Objective-C Compatibility Header : YES 

A continuación, limpie el proyecto y compile una vez, después de que la comstackción tenga éxito (probablemente debería) importar debajo del archivo de encabezado en su archivo object-c class .m

 #import "YourProjectName-Swift.h" 

Boooom!

También probablemente sea útil para aquellos de ustedes con un objective de Marco :

La statement de importación del archivo de encabezado generado automáticamente se ve un poco diferente de los objectives de la aplicación. Además de las otras cosas mencionadas en otras respuestas, use

 #import  

en lugar de

 #import "ProductModuleName-Swift.h" 

según la documentación de Apple sobre Mix & Match para objectives de marco.

Asegúrese de que su proyecto define un módulo y le ha dado un nombre al módulo. A continuación, vuelva a generar, y Xcode creará el archivo de encabezado -Swift.h y podrá importar.

Puede establecer la definición del módulo y el nombre del módulo en la configuración de su proyecto.

Tuve el mismo problema y resultó que los símbolos especiales en el nombre del módulo se reemplazan por xcode (en mi caso los guiones terminaron siendo subrayados). En la configuración del proyecto, verifique “nombre del módulo” para encontrar el nombre del módulo para su proyecto. Después de eso, use ModuleName-Swift.h o cambie el nombre del módulo en la configuración.

El archivo se crea automáticamente (hablando de Xcode 6.3.2 aquí). Pero no lo verá, ya que está en su carpeta Derived Data. Después de marcar su clase rápida con @objc , comstackr, luego busque Swift.h en su carpeta Derived Data. Deberías encontrar el encabezado Swift allí.

Tuve el problema, que Xcode renombró my my-Project-Swift.h a my_Project-Swift.h Xcode no le gusta "." "-" "." "-" símbolos etc. Con el método anterior, puede encontrar el nombre del archivo e importarlo a una clase Objective-C.

Solo incluye #import “myProject-Swift.h” en archivos .m o .h

PD: no encontrará “myProject-Swift.h” en el inspector de archivos oculto. Pero es generado por la aplicación de forma automática.

Detalles: proyecto Objective-C con código Swift 3 en Xcode 8.1

Tareas:

  1. Usa la enumeración rápida en la clase objective-c
  2. Usar objective-c enum en clase rápida

MUESTRA COMPLETA

1. Clase Objective-C que usa Swift enum

ObjcClass.h

 #import  typedef NS_ENUM(NSInteger, ObjcEnum) { ObjcEnumValue1, ObjcEnumValue2, ObjcEnumValue3 }; @interface ObjcClass : NSObject + (void) PrintEnumValues; @end 

ObjcClass.m

 #import "ObjcClass.h" #import "SwiftCode.h" @implementation ObjcClass + (void) PrintEnumValues { [self PrintEnumValue:SwiftEnumValue1]; [self PrintEnumValue:SwiftEnumValue2]; [self PrintEnumValue:SwiftEnumValue3]; } + (void) PrintEnumValue:(SwiftEnum) value { switch (value) { case SwiftEnumValue1: NSLog(@"-- SwiftEnum: SwiftEnumValue1"); break; case SwiftEnumValue2: case SwiftEnumValue3: NSLog(@"-- SwiftEnum: long value = %ld", (long)value); break; } } @end 

Detecta el código Swift en código Objective-C

En mi ejemplo, uso SwiftCode.h para detectar el código Swift en Objective-C. Este archivo se genera automáticamente (no creé una copia física de este archivo de encabezado en un proyecto) y solo puede establecer el nombre de este archivo:

enter image description here

enter image description here

Si el comstackdor no puede encontrar el código SWIFT de su archivo de encabezado, intente comstackr el proyecto.

2. Clase Swift que usa el enunciado Objective-C

 import Foundation @objc enum SwiftEnum: Int { case Value1, Value2, Value3 } @objc class SwiftClass: NSObject { class func PrintEnumValues() { PrintEnumValue(.Value1) PrintEnumValue(.Value2) PrintEnumValue(.Value3) } class func PrintEnumValue(value: ObjcEnum) { switch value { case .Value1, .Value2: NSLog("-- ObjcEnum: int value = \(value.rawValue)") case .Value3: NSLog("-- ObjcEnum: Value3") break } } } 

Detecta código Objective-C en código Swift

Necesita crear un archivo de encabezado de puente. Cuando agrega un archivo Swift en el proyecto Objective-C o un archivo Objective-C en un proyecto rápido, Xcode le sugerirá que cree un encabezado puente.

enter image description here

Puede cambiar el nombre del archivo de encabezado puente aquí:

enter image description here

Bridging-Header.h

 #import "ObjcClass.h" 

Uso

 #import "SwiftCode.h" ... [ObjcClass PrintEnumValues]; [SwiftClass PrintEnumValues]; [SwiftClass PrintEnumValue:ObjcEnumValue3]; 

Resultado

enter image description here


MÁS MUESTRAS

Pasos completos de integración Objective-c y Swift descritos anteriormente . Ahora escribiré algunos otros ejemplos de código.

3. Llame a la clase Swift desde el código Objective-c

Clase Swift

 import Foundation @objc class SwiftClass:NSObject { private var _stringValue: String var stringValue: String { get { print("SwiftClass get stringValue") return _stringValue } set { print("SwiftClass set stringValue = \(newValue)") _stringValue = newValue } } init (stringValue: String) { print("SwiftClass init(String)") _stringValue = stringValue } func printValue() { print("SwiftClass printValue()") print("stringValue = \(_stringValue)") } } 

Código Objective-C (código de llamada)

 SwiftClass *obj = [[SwiftClass alloc] initWithStringValue: @"Hello World!"]; [obj printValue]; NSString * str = obj.stringValue; obj.stringValue = @"HeLLo wOrLd!!!"; 

Resultado

enter image description here

4. Llamar a la clase Objective-c desde el código Swift

Clase Objective-C (ObjcClass.h)

 #import  @interface ObjcClass : NSObject @property NSString* stringValue; - (instancetype) initWithStringValue:(NSString*)stringValue; - (void) printValue; @end 

ObjcClass.m

 #import "ObjcClass.h" @interface ObjcClass() @property NSString* strValue; @end @implementation ObjcClass - (instancetype) initWithStringValue:(NSString*)stringValue { NSLog(@"ObjcClass initWithStringValue"); _strValue = stringValue; return self; } - (void) printValue { NSLog(@"ObjcClass printValue"); NSLog(@"stringValue = %@", _strValue); } - (NSString*) stringValue { NSLog(@"ObjcClass get stringValue"); return _strValue; } - (void) setStringValue:(NSString*)newValue { NSLog(@"ObjcClass set stringValue = %@", newValue); _strValue = newValue; } @end 

Swift code (código de llamada)

 if let obj = ObjcClass(stringValue: "Hello World!") { obj.printValue() let str = obj.stringValue; obj.stringValue = "HeLLo wOrLd!!!"; } 

Resultado

enter image description here

5. Use la extensión Swift en código Objective-c

Extensión Swift

 extension UIView { static func swiftExtensionFunc() { NSLog("UIView swiftExtensionFunc") } } 

Código Objective-C (código de llamada)

 [UIView swiftExtensionFunc]; 

6. Usa la extensión Objective-c en código rápido

Extensión Objective-C (UIViewExtension.h)

 #import  @interface UIView (ObjcAdditions) + (void)objcExtensionFunc; @end 

UIViewExtension.m

 @implementation UIView (ObjcAdditions) + (void)objcExtensionFunc { NSLog(@"UIView objcExtensionFunc"); } @end 

Swift code (código de llamada)

 UIView.objcExtensionFunc() 

Hay dos condiciones,

  • Use su archivo rápido en el archivo objective c.
  • Usa tu archivo objective c en un archivo rápido.

Entonces, para ese propósito, debes seguir estos pasos:

  • Agregue su archivo rápido en un proyecto Object-C o viceversa.
  • Crear archivo de encabezado (.h).
  • Vaya a Configuraciones de comstackción y realice los pasos a continuación con la búsqueda,

    1. busque este texto “brid” y establezca una ruta de su archivo de encabezado.
    2. “Define el módulo”: SÍ.
    3. “Bibliotecas estándar siempre integradas de Swift”: SÍ.
    4. “Instalar el encabezado de compatibilidad de Objective-C”: SÍ.

Después de eso, limpia y reconstruye tu proyecto.

Use su archivo rápido en el archivo objective c.

En ese caso, primero escriba “@objc” antes de su clase en un archivo rápido.

Después de eso, en su archivo objective c, escriba esto,

  #import "YourProjectName-Swift.h" 

Usa tu archivo objective c en un archivo rápido.

En ese caso, en su archivo de encabezado, escriba esto,

  #import "YourObjective-c_FileName.h" 

Espero que esto ayude.

@sig answer es uno de los mejores, sin embargo, no funcionó para mí con el proyecto anterior (¡no es nuevo!), necesitaba algunas modificaciones. Después de muchas variaciones, encontré la receta para mí (usando XCode 7.2):

  1. Nombre del módulo de producto: $ (PRODUCT_NAME: c99extidentifier)
  2. Define el Módulo: NO
  3. El contenido incrustado contiene Swift: NO
  4. Instalar el encabezado de compatibilidad de Objective-C: SÍ
  5. Objective-C Bridging Header: ProjectName-Bridging-Header.h

El último punto (5) fue crucial. Lo puse solo en la segunda sección (campo Objetivos), el campo Proyecto debe dejarse vacío: enter image description here De lo contrario, no generó el archivo correcto “Project-Swift.h” para mí (no incluía métodos rápidos).

En mi caso, aparte de estos pasos:

  1. Nombre del módulo de producto: myproject
  2. Define el Módulo: SÍ
  3. El contenido incrustado contiene Swift: SÍ
  4. Instalar el encabezado de compatibilidad de Objective-C: SÍ
  5. Encabezado puente de Objective-C: $ (SRCROOT) /Sources/SwiftBridging.h

He necesitado poner la clase como pública para crear el archivo productName-Swift.h :

 import UIKit @objc public class TestSwift: NSObject { func sayHello() { print("Hi there!") } } 

Acabo de descubrir que agregar un directorio de archivos rápidos a un proyecto no funcionará. Primero debe crear un grupo para el directorio y luego agregar los archivos rápidos …

Tuve el mismo problema y finalmente parecía que no estaban apegados a los mismos objectives. La clase ObjC se adjunta a Target1 y Target2, la clase Swift solo se adjunta al Target1 y no es visible dentro de la clase ObjC.

Espero que esto ayude a alguien.

Tengo el mismo error: no se encontró el archivo myProjectModule-Swift.h “, pero, en mi caso, el motivo real estaba en el destino de despliegue incorrecto:” Swift no está disponible en OS X anterior a 10.9; establezca MACOSX_DEPLOYMENT_TARGET en 10.9 o posterior (actualmente es ’10 .7 ‘) “por lo tanto, cuando cambie el destino de despliegue a 10.9, el proyecto se compiló correctamente.

Mi problema era que la generación automática del archivo -swift.h no podía entender una subclase de CustomDebugStringConvertible. Cambié la clase para ser una subclase de NSObject en su lugar. Después de eso, el archivo -swift.h ahora incluía la clase correctamente.

mi problema fue que me quedé atascado después de que xcode creara el archivo puente, pero aun así obtuve un error en el nombre del archivo de encabezado MYPROJECTNAME-swift.h

1.I check in terminal y busco todos los archivos de puente swift creados automáticamente:

find ~/library/Developer/Xcode/DerivedData/ -name "*-Swift.h"|xargs basename|sort -

ves lo que xcode creó.

  1. en mi caso, tuve espacio en el nombre de mi proyecto y xcode replace this is ‘_’

Tuve problemas en que agregaría clases a mi encabezado de puente objective-c, y en aquellos encabezados de objective-c que se importaron, estaban tratando de importar el encabezado veloz. No me gustó eso.

Así que en todas mis clases object-c que usan swift, pero también están puenteadas, la clave fue asegurarse de usar declaraciones de clase forward en los encabezados, luego importar el archivo “* -Swift.h” en el archivo .m.

No tuve que cambiar ninguna configuración en la comstackción o agregar @obj a la clase.

Todo lo que tuve que hacer fue crear bridge-header, que se creó automáticamente cuando creé clases Swift en el proyecto Objective-c. Y luego solo tuve que hacer

importar “Bedtime-Swift.h” <- dentro del archivo object-c que necesitaba usar ese archivo rápido.

Bueno, después de leer todos los comentarios e intentar y leer e intentar de nuevo, logré incluir clases rápidas en mi proyecto Big obj-c. Entonces, gracias por toda la ayuda. Quería compartir un consejo que me ayudó a comprender mejor el proceso. En la clase .m, fui a la línea de importación del nombre de destino rápido #import “myTargetName-Swift.h” y pulsé la tecla:

comando + clic del mouse -> saltar a la definición enter image description here

Allí puedes ver toda la traducción de swift a obj-c y encontrarás las diversas funciones re-declaradas en obj-c. Espero que este consejo te ayude tanto como me ayudó.