Objective - C pidiendo asignación en la clase swift


Algunos pequeños pasos para comenzar a envolver mi cabeza alrededor de Swift. Básicamente he portado una clase antigua que simplemente encuentra el icono correspondiente para un nombre y devuelve la imagen UIImage apropiada. La parte Rápida de las cosas parece estar en marcha, y se ve (casi) así:

@objc class ImageHandler{

    func iconForData(data: MyData) -> UIImage{
        let imagesAndNames = [
            "1": "tree.png",
            "2": "car.png",
            "3": "house.png",
            "7": "boat.png",
        ]

        var imageName: String? = imagesAndNames[data.imageName]
        if !imageName{
            imageName = "placeholder.png"
        }
        let icon = UIImage(named: imageName)
        return icon
    }
}

No hay advertencias en lo anterior. Sin embargo, mi vieja clase Objective-C está pidiendo un método alloc en la clase swift.

ImageHandler *imageHandler = [ImageHandler alloc] init];

Devuelve el error "No known class method for selector 'alloc' which is es cierto, supongo, pero ¿cómo puedo escapar de esto? ¿Tendré que basar mi clase swift de NSObject para evitar esto?

Author: GoZoner, 2014-06-04

5 answers

Declaras tu clase ImageHandler como clase raíz. No tiene alloc método en sí. Usted necesita heredar de NSObject:

@objc class ImageHandler : NSObject {

    ...

}

Referenciado desde este hilo ADF.

 47
Author: akashivskyy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-06-04 13:58:03

Solo quería comentar aquí que si no desea subclase NSObject o cualquier otro objeto ObjC, puede declarar un inicializador de nivel de clase:

@objc class ImageHandler{

    class func newInstance() -> ImageHandler {
        return ImageHandler()
    }

    func iconForData(data: MyData) -> UIImage{
        let imagesAndNames = [
            "1": "tree.png",
            "2": "car.png",
            "3": "house.png",
            "7": "boat.png",
        ]

        var imageName: String? = imagesAndNames[data.imageName]
        if !imageName{
            imageName = "placeholder.png"
        }
        let icon = UIImage(named: imageName)
        return icon
    }
}

Luego en ObjC

ImageHandler * imageHandler = [ImageHandler newInstance];

De esta manera, no tiene que depender de la herencia de clase ObjC a menos que lo desee.

 24
Author: Logan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-06-07 01:29:17

Esta respuesta es si desea seguir utilizando objetos swift puros, y no desea heredar de NSObject. Si no le importa usar objetos swift puros, use la respuesta de akashivskyy anterior.

Me encontré con este mismo problema. Tomé la respuesta de Logan y la modificé para que la persona que llama a Objective-C no tenga que cambiar de comportamiento. Esto es especialmente importante si estás haciendo como yo y construyendo un marco que podría ser consumido por Objective-C o Swift proyecto.

@objc public class TestClass {

    public init(){}

    public class func alloc() -> TestClass {return TestClass()}

}

La implementación de Objective-C se mantiene familiarizada.

TestClass *testClass = [[TestClass alloc] init];

La implementación de Swift también se mantiene igual.

let testClass = TestClass()

Editar: Además, pasé a implementar esto en una clase que puede ser subclasificada por otros objetos swift puros.

@objc public class ObjectiveCCompatibleObject {

    required public init(){}

    public class func alloc() -> Self {return self()}
}
 2
Author: CaseyB,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-11-25 15:00:30

Si queremos importar el archivo swift en Objective C, debemos hacer

Importar "nombre del producto-Swift.h " o utilizar corchetes angulares

En el archivo de Objective C. Luego puede acceder a alloc, init para una clase swift importada específica en Objective C.

 1
Author: Vinay Podili,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-09-02 06:08:35

Usted podría hacer esto:

ImageHandler *imageHandler =
    [[NSClassFromString(@"YourProjectName.ImageHandler") alloc] init];

(o, si hubieras hecho @objc(ImageHandler) class ImageHandler en Swift, harías [[NSClassFromString(@"ImageHandler") alloc] init])


Alternativamente, puede declarar (pero no implementar) una categoría ficticia que contenga el método alloc en la parte superior de su archivo Objective-C:

@interface ImageHandler (Dummy)
+ (instancetype)alloc;
@end

Y luego puedes usarlo directamente en tu código:

ImageHandler *imageHandler = [[ImageHandler alloc] init];
 -1
Author: newacct,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-11-25 05:26:39