Disons que je définis une classe générique dans Swift, semblable à la suivante:
class MyArray<T> {
func addObject(object: T) {
// do something... hopefully
}
}
(Je sais qu'il existe un légèrementmeilleure implémentation de array, ce n'est qu'un exemple.)
Dans Swift, je peux maintenant utiliser cette classe très facilement:
let a = MyArray<String>()
a.addObject("abc")
Avec Xcode 7, nous avons maintenant des génériques dans Objective-C , je suppose donc que je pourrais utiliser cette classe dans Objective-C:
MyArray<NSString*> *a = [[MyArray<NSString*> alloc] init];
[a addObject:@"abc"];
Cependant, MyArray n'est jamais ajouté à mon fichier Project-Swift.h
. Même si je le modifie pour qu'il hérite de NSObject, il n'apparaît toujours pas dans mon fichier Swift.h.
Est-il possible de créer une classe Swift générique et de l'utiliser ensuite dans Objective-C?
Mise à jour: Si je tente d'hériter de NSObject et d'annoter avec @objc:
@objc(MyArray)
class MyArray<T>: NSObject {
func addObject(object: T) {
// do something... hopefully
}
}
Je reçois l'erreur suivante du compilateur:
Les sous-classes génériques des classes '@objc' ne peuvent pas avoir d'attribut '@objc' explicite, car elles ne sont pas directement visibles depuis Objective-C.
Cela signifie-t-il qu'il n'y a aucun moyen d'utiliser une classe Swift générique dans Objective-C?
Comment on indirectementréférence la classe?
Les types génériques Swift ne peuvent pas être utilisés dans Objective-C.
Cela exclut les fonctionnalités réservées à Swift, telles que celles répertoriées ici:
- Génériques
- ...
Il existe une solution de contournement dans certaines situations, lorsque vous devez importer une classe générique Swift dans Objective-C.
Supposons que vous ayez le service Swift REST, qui utilise des génériques. J'utilise le framework Moya
et voici à quoi ressemble mon service:
class AuthService: BaseService<AuthAPI> {
func register(email: String) {
// ...
}
}
Il est hérité du service de base utilisant des génériques, je ne peux donc pas l'utiliser directement dans mon code Objective-C.
Donc, voici une solution de contournement:
Permet de créer AuthServiceProtocol
:
@objc protocol AuthServiceProtocol {
func register(email: String)
}
Ensuite, créons une fabrique pour le service (ou une méthode singleton, aucune différence):
@objc class Services: NSObject {
static let authService: AuthServiceProtocol = AuthService()
}
Ensuite, je peux appeler mon service générique d’authentification Swift à partir du code Objective-C:
- (void)someObjcMethod {
[Services.authService registerWithEmail:self.email];
}
C'est fastidieux et moche, mais vous pouvez définir une classe générique dans Swift, puis en exposer les spécialisations dans Objective-C:
public class MyArray<T> {
public func addObject(object: T) {
// do something... hopefully
}
}
@objc
public class MyArrayOfAny: MyArray<Any> {
@objc
public override func addObject(object: Any) {
super.addObject(object: object)
}
}
@objc
public class MyArrayOfString: MyArray<String> {
@objc
public override func addObject(object: String) {
super.addObject(object: object)
}
}