objective-c - quick - swift version
Objective-C que pide la asignación en clase rápida (5)
Unos pequeños pasos para comenzar a envolver mi cabeza alrededor de Swift. Básicamente, porté una clase antigua que simplemente encuentra el ícono correspondiente para un nombre y devuelve el UIImage apropiado. La parte rápida de las cosas parece estar lista y funcionando, 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 sobre lo anterior. Sin embargo, mi antigua clase Objective-C está pidiendo un método de asignación en la clase swift.
ImageHandler *imageHandler = [ImageHandler alloc] init];
Devuelve el error "No se conoce un método de clase para el selector ''alloc'' que es lo suficientemente cierto, supongo, pero ¿cómo puedo evitarlo? ¿Tendré que basar mi clase swift de NSObject para evitar esto?
Esta respuesta es si desea seguir utilizando objetos swift puros y no desea heredar de NSObject. Si no te importa usar objetos puros y rápidos, usa la respuesta de akashivsky arriba.
Me encontré con este mismo problema. Tomé la respuesta de Logan y la modifiqué para que la persona que llama a Objective-C no tenga que cambiar de comportamiento. Esto es especialmente importante si lo está haciendo como yo y construyendo un marco que podría ser consumido por los proyectos de Objective-C o Swift.
@objc public class TestClass {
public init(){}
public class func alloc() -> TestClass {return TestClass()}
}
La implementación de Objective-C llega a ser familiar.
TestClass *testClass = [[TestClass alloc] init];
La implementación rápida también se mantiene igual.
let testClass = TestClass()
Edit: Además, continué implementando 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()}
}
Podrías hacer esto:
ImageHandler *imageHandler =
[[NSClassFromString(@"YourProjectName.ImageHandler") alloc] init];
(o, si hubiera hecho la @objc(ImageHandler) class ImageHandler
en Swift, haría [[NSClassFromString(@"ImageHandler") alloc] init]
)
Alternativamente, puede declarar (pero no implementar) una categoría ficticia que contiene el método de alloc
en la parte superior de su archivo de Objective-C:
@interface ImageHandler (Dummy)
+ (instancetype)alloc;
@end
Y luego puedes usarlo directamente en tu código:
ImageHandler *imageHandler = [[ImageHandler alloc] init];
Si queremos importar un archivo swift en Objective C, deberíamos hacer
importe "productname-Swift.h" o use corchetes angulares <>
en el archivo de Objective C. Luego puede acceder a alloc, init para una clase swift importada específica en el Objetivo C.
Solo quería comentar aquí que si no desea subclasificar 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 la Clase ObjC a menos que desee.
Usted declara su clase ImageHandler
como una clase raíz. No tiene método de alloc
sí. Necesitas heredar de NSObject
:
@objc class ImageHandler : NSObject {
...
}
Referenciado desde este hilo ADF .