web-dev-qa-db-fra.com

Utilisation d'une classe Swift générique dans Objective-C

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?

17
Senseful

Les types génériques Swift ne peuvent pas être utilisés dans Objective-C.

https://developer.Apple.com/library/content/documentation/Swift/Conceptual/BuildingCocoaApps/MixandMatch.html#//Apple_ref/doc/uid/TP40014216-CH10-ID136

Cela exclut les fonctionnalités réservées à Swift, telles que celles répertoriées ici:

  • Génériques
  • ...
20
newacct

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];
}
5
medvedNick

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)
  }
}
0
Mapache