¿Puede el código objetivo-c llamar a la extensión rápida en Class?

94

Busqué algunas publicaciones, creo que no puedo escribir una extensión en Swift y llamarla desde el código Objective-C, ¿verdad?

¿Los atributos similares a @objc solo admiten métodos, clases, protocolos?

sprhawk
fuente
1
¿Por qué no lo intentas?
TIENE el
7
ide se quejó de error, pero quiero obtener una respuesta definitiva.
sprhawk

Respuestas:

84

Puede escribir una extensión Swift y usarla en el código Objective-C. Probado con XCode 6.1.1.

Todo lo que necesitas hacer es:

  • crea tu extensión en Swift (sin @objcanotaciones)

  • #import "ProjectTarget-Swift.h" en su clase Objective-C (donde "ProjectTarget" representa el destino XCode con el que está asociada la extensión Swift)

  • llamar a los métodos desde la extensión Swift

Actualización: a partir de @Rizwan Ahmed mencionado, debe agregar una @objcanotación:

A partir de Swift 4.0.3, se necesita la anotación @objc si desea utilizar la extensión en los archivos de clase Objective C.

marius bardan
fuente
6
He hecho exactamente esto, pero sigue siendo un error de tiempo de compilación. Hmmm. EDITAR: importé mi encabezado de puente, en lugar de "ProjectTarget-Swift.h". Der.
Jason Renaldo
Ambos son encabezados puente. La diferencia es que uno es para usar código Swift en ObjC y el otro es para usar código ObjC en Swift. El encabezado Swift es invisible. El otro, debe ser administrado por usted.
marius bardan
William Hu, mira la respuesta de McLaughlinj.
appleitung
39
A partir de Swift 4.0.3, se necesita la anotación @objc si desea utilizar la extensión en los archivos de clase Objective C.
Rizwan Ahmed
68

Descubrí que en Swift 4.0 tenía que agregar @objcdelante de mi palabra clave de extensión para que los métodos de extensión Swift fueran visibles por una instancia de la clase Objc que estaba extendiendo.

En breve:

Configuración de archivo de configuración:

CustomClass.h
CustomClass.m
CustomClassExtension.swift

En CustomClassExtension:

@objc extension CustomClass
{
    func method1() 
    {
        ...
    }
}

En mi AppDelegate.m:

self.customClass = [[CustomClass alloc] init];
[self.customClass method1];
Andrey P.
fuente
2
Si un método usa genéricos, Objective-C no puede usarlo y deberá agregar la @nonobjcanotación.
ThomasW
Solo una nota al margen, @objcMembers no funciona en este caso. No sé por qué ... :-(
Raunak
46

Esta solución funciona para Swift 2.2 y Swift 3 . Tenga en cuenta que solo las extensiones para clases (no para estructuras o enumeraciones) serán accesibles desde Objective-C.

import UIKit

extension UIColor {

    //Custom colours
    class func otherEventColor() -> UIColor {
        return UIColor(red:0.525, green:0.49, blue:0.929, alpha:1)
    }
}

Luego, #importe "ProductModuleName-Swift.h" en su archivo ObjC.

Rápido 4

extension UIColor {

    // As of Swift 4.0.3, the @objc annotation is needed if you want to use the extension in Objective-C files
    @objc
    class func otherEventColor() -> UIColor {
        return UIColor(red:0.525, green:0.49, blue:0.929, alpha:1)
    }
}
Foti Dim
fuente
No es "YourProjectsNameHere ..." sino "YourTargetsNameHere ...": para compartir objetivos, debe bloquearlo con el nombre: dr2050.postach.io/post/…
Dan Rosenstark
1
@DanRosenstark Tienes razón. Lo voy a cambiar a "ProductModuleName-Swift.h" como sugiere Apple: developer.apple.com/library/ios/documentation/Swift/Conceptual/…
Foti Dim
1
Funciona bien para Swift 3.
Viktor Kucera
¿Hay alguna razón por la que dices que publices necesario? Funciona bien sin publicmodificador para mí. ¿Estamos asumiendo que la extensión no está en el mismo proyecto sino que se está importando de otro proyecto?
Lee Kang
¿Necesito usar un encabezado puente?
jegadeesh
42

Como se explica en las otras respuestas, la importación del encabezado Swift generado funciona en la mayoría de los casos .

Una excepción a esto es cuando la categoría se define en un tipo puente (es decir, la extensión se define en Stringy no NSString). Estas categorías no se vincularán automáticamente con sus contrapartes de Objective-C. Para evitar esto, deberá usar el tipo Objective-C (y emitir el valor de retorno en su código Swift con as String) o definir una extensión para los tipos Swift y Objective-C.

McLaughlinj
fuente
2
Además de la respuesta anterior, debe hacer pública su extensión rápida y establecer su tipo como NSString, por ejemplo public extension NSString. Si obtiene un identificador no resuelto o un error similar en el momento de la compilación, puede volver a let sVal = self as StringsVal
enviarlo
@RunLoop en realidad no necesita público, funcionará sin un especificador de alcance. Y (me refiero a exportar a Obj-C) no funciona para Strings, porque son estructuras, no clases y solo están disponibles en Swift. Entonces, sí, puede escribir extensión para NSString y usar cast, o escribir extensiones, como se mclaughlinjdijo, tanto para la clase NSString como para la estructura String
Alex Nazarsky
3

Importe el encabezado "#import" ProductModuleName-Swift.h " en el archivo objetivo-c y agregue @objc delante de su extensión en un archivo rápido. Funcionará bien en swift 4.2 y swift 5

Ranjani
fuente