web-dev-qa-db-fra.com

Les déclarations dans les extensions ne peuvent pas encore remplacer l'erreur dans Swift 4

J'ai une extension:

public extension UIWindow {
    override public func topMostController()->UIViewController? { ... }
}

mais pour mon topMostController j'obtiens l'erreur suivante:

Declarations in extensions cannot override yet error

Cela fonctionne bien pour Swift 3.1, mais pour Swift 4, je reçois cette erreur. Comment peut-il être corrigé? Qu'ont-ils changé en Swift 4?

62
J. Doe

Cela fonctionnera si vous faites l'implémentation de base @objc. Voir réponse de Hamish pour une explication détaillée sur les composants internes.

Remplacer les méthodes déclarées dans les extensions est un peu délicat à faire correctement. Objective-C le soutient, mais ce n’est pas absolument sûr. Swift vise à le faire mieux. La proposition n'est pas encore terminée.

Version actuelle de la proposition disponible ici .

66
Sulthan

Les extensions peuvent ajouter de nouvelles fonctionnalités à un type, mais elles ne peuvent pas remplacer les fonctionnalités existantes.

Les extensions ajoutent de nouvelles fonctionnalités à une classe, une structure, une énumération ou un type de protocole existant. Cela inclut la possibilité d'étendre des types pour lesquels vous n'avez pas accès au code source d'origine (connu sous le nom de modélisation rétroactive).

Les extensions dans Swift peuvent:

  • Ajouter des propriétés d'instance calculées et des propriétés de type calculées
  • Définir des méthodes d'instance et des méthodes de type
  • Fournir de nouveaux initialiseurs
  • Définir les indices
  • Définir et utiliser de nouveaux types imbriqués
  • Rendre un type existant conforme à un protocole

Guide du développeur Apple

Vous essayez de faire est similaire à ce que fait par ce code:

class MyClass: UIWindow {
    func myFunc() {}
}

extension MyClass {
    override func myFunc() {}
}

NOTE: Si vous voulez override topMostController(), créez une sous-classe de UIWindow

12
Nikhlesh Bagdiya

Swift 5.0

En fait, il y a peu de problèmes dans le code OP:

  1. UIView (qui est la super-classe de UIWindow) n'a pas de méthode topMostController(), c'est pourquoi vous ne pouvez pas la remplacer.

  2. Apple n'encourage pasoverride func à l'intérieur extension:

    Les extensions peuvent ajouter de nouvelles fonctionnalités à un type, mais elles ne peuvent pas remplacer les fonctionnalités existantes.

  3. Si vous souhaitez toujours remplacer une fonction dans une extension, il existe deux méthodes:

[A] Marquez votre fonction avec @objc dynamic func dans la classe parente:

class Vehicle {
    @objc dynamic func run() { /* do something */ }
}

class Car: Vehicle { }

extension Car {
    override func run() { /* do another thing */ }
}

[B] Fonction de substitution des classes internes, qui est le descendant de NSObject.

 extension UIWindow {
    // UIWindow is a descendant of NSObject, and its superclass UIView has this function then you can override
    override open func becomeFirstResponder() -> Bool {
        ...
        return super.becomeFirstResponder()
    }
 }
1
nahung89