0

J'ai un framework iOS que je suis en train de passer à Swift 3. J'aimerais que les signatures de méthodes de l'API suivent les conventions de Swift 3 en utilisant un premier paramètre nommé pour les méthodes tout en conservant la rétrocompatibilité. Il est assez facile d'ajouter de nouvelles signatures de méthode API et de déprécier les anciennes. Mais quelle est la meilleure façon de gérer cela avec les protocoles utilisés par les délégués?Mise à niveau des protocoles obsolètes pour la mise à niveau de Swift 3

API pour 2.x Swift:

@objc(FooManager) 
public class FooManager { 
    public var delegate: FooManagerDelegate? 
    public func saveFoo(foo: Foo) { 
    ...  
    delegate?.didSaveFoo(foo) 
    } 
... 
} 

@objc public protocol FooManagerDelegate { 
    @objc optional func didSaveFoo(foo: Foo) 
} 

Nouvelle API pour 3.x Swift:

@objc(FooManager) 
public class FooManager { 
    public var delegate: FooManagerDelegate? 

    @available(*, deprecated, message: "use didSave(foo: foo)") 
    public func saveFoo(foo: Foo) { 
    ...  
    delegate?.didSaveFoo(foo) 
    } 
    public func save(foo: Foo) { 
    ...  
    delegate?.didSave(foo: foo) 
    } 
... 
} 

@objc public protocol FooManagerDelegate { 
    @objc optional func didSaveFoo(foo: Foo) 
    @objc optional func didSave(foo: Foo) 
} 

La solution ci-dessus fonctionnera, mais il ne donnera aucun avertissement de désapprobation à utilisateurs pour continuer à utiliser les anciennes méthodes de délégué. Je pourrais créer un nouveau délégué et déprécier l'ancienne classe de délégué, mais je finirais par avoir une classe de délégué et un nom de propriété non standard. Je ne voudrais pas que mon FooManager laid regarder comme ceci:

public class FooManager { 
    @available(*, deprecated, message: "use swift3delegate") 
    public var delegate: FooDelegate? 
    public var swift3delegate: Swift3FooDelegate? 

Y at-il des meilleures solutions pour les utilisateurs migrer vers de nouvelles signatures de méthode de protocole, tout en maintenant la compatibilité ascendante?

Répondre

1

Exactement ce que vous demandez n'est pas possible dans Swift (ni Objective-C?) À ma connaissance. Citant un response to a related question:

Le principal problème avec lancer un avertissement de dévalorisation sur une classe qui est conforme à MyProtocol et mis en œuvre myOldFunction() est qu'il n'y a rien de mal avec les classes implémentation de fonctions et les propriétés qui ne font pas partie de votre protocole.

C'est que la méthode de protocole est dépréciée ne signifie pas nécessairement que le plan de la méthode est universellement à éviter, il pourrait simplement dire que, aux fins de conformité à ce protocole, la méthode ou la propriété en question est maintenant obsolète.

Je vois tout à fait le point pour cela et j'aimerais cette fonctionnalité aussi, mais à ma connaissance Swift 3 au moins ne l'offre pas (pas plus que Objective-C à ma connaissance). Une solution pour cela serait de déprécier l'ensemble du protocole et de produire un nouveau protocole dont vous avez besoin pour déclarer la conformité à votre code Swift 3. Donc, cela fonctionne:

@available(*, deprecated, message="use ModernX instead") 
protocol X {} 

class A: X {} 

... et dans votre protocole ModernX comprennent simplement toutes les méthodes, sauf pour la méthode désapprouvée (s). l'idée d'utiliser un protocole de base est utile

protocol BaseX { 
    func foo() 
    func bar() 
} 

@available(*, deprecated, message: "Use ModernX instead") 
protocol X: BaseX { 
    func theDeprecatedFunction() 
} 

protocol ModernX: BaseX { 
    func theModernFunction() 
} 

// you'll get a deprecation warning here. 
class A: X { 
    func foo() {} 
    func bar() {} 

    func theDeprecatedFunction() { 
    } 
} 
+0

Merci,: en utilisant un protocole de base sans la méthode désapprouvée pourrait rendre ce un peu moins maladroit, mais il est une jolie solution passe-partout lourde à coup sûr. De cette façon, j'ai seulement besoin d'une propriété 'delegate' dans la classe manager. Je souhaite juste ne pas avoir à faire un nouveau protocole avec un nom drôle - mon protocole Swift 2 a le nom que je veux utiliser. :( – davidgyoung

+0

Si votre propre code est la seule implémentation du protocole par exemple dans la même cible/projet/espace de travail (ie dans un paramètre qui serait simple à rechercher et remplacer), vous pouvez toujours le renommer comme "... Legacy " ou quelque chose.Mais oui, je ne peux pas dire que je suis excité par cette solution de contournement d'une autre manière que cela, il isole soigneusement les choses obsolètes dans une unité (le protocole avec juste des choses obsolètes). – mz2