Alors que je pense que je peux répondre à votre question, ce n'est pas une réponse que vous aimez.
TL;DR: @objc
fonctions peuvent ne pas être actuellement dans les extensions de protocole. Vous pouvez créer une classe de base au lieu de cela, si ce n'est pas une solution idéale.
Les Extensions de protocole et Objective-C
Tout d'abord, cette question/réponse (Peut Swift Méthode Définie sur les Extensions de Protocoles Accessibles en Objective-c) semble suggérer que, en raison de la façon dont les extensions de protocole sont expédiées sous le capot, les méthodes déclarées dans les extensions de protocole ne sont pas visibles à l' objc_msgSend()
la fonction, et donc ne sont pas visibles à l'Objective-C du code. Puisque la méthode que vous essayez de définir dans votre extension doit être visible pour Objective-C (so UIKit
pouvez l'utiliser), il hurle à vous de ne pas inclure @objc
, mais une fois que vous faites l'inclure, il hurle à vous, car @objc
n'est pas permis dans les extensions de protocole. C'est probablement parce que les extensions de protocole ne sont pas actuellement en mesure d'être visible à l'Objective-C.
Nous pouvons également voir que le message d'erreur une fois que nous ajoutons @objc
états "@objc peut être utilisé uniquement avec des membres de classes, @objc de protocoles et de béton extensions de classes." Ce n'est pas une classe; une extension à une @objc protocole n'est pas la même chose que d'être dans la définition de protocole lui-même (c'est à dire dans les exigences), et le mot "concret" suggère qu'une extension du protocole ne compte pas comme un béton de classe de l'extension.
Solution de contournement
Malheureusement, ce à peu près complètement vous empêche d'utiliser les extensions de protocole lorsque les implémentations par défaut doit être visible à l'Objective-C cadres. Au début, j'ai pensé que peut - @objc
n'a pas été autorisé dans votre extension de protocole parce que la Swift Compilateur ne peut pas garantir que de la conformation de types serait classes (même si vous avez spécifié UIViewController
). Alors j'ai mis un class
exigence sur P1
. Cela n'a pas fonctionné.
Peut-être la seule solution est d'utiliser simplement une classe de base à la place d'un protocole ici, mais ce n'est évidemment pas complètement idéal, car une classe ne peut avoir qu'une seule classe de base, mais se conformer à de multiples protocoles.
Si vous choisissez d'aller dans cette voie, merci de prendre cette question (Swift 3 ObjC Protocole Facultatif Méthode n'est Pas Appelée dans la sous-classe) en compte. Il semble qu'un autre sujet d'actualité dans Swift 3, c'est que les sous-classes n'hérite pas automatiquement le protocole facultatif exigence de mise en œuvre de leurs super-classe. La réponse à cette questions dans le cadre d'une adaptation de l' @objc
de la contourner.
Signaler le Problème
Je pense que c'est en cours de discussion déjà parmi ceux qui travaillent sur la Swift projets open source, mais vous pouvez être sûr qu'ils sont au courant, soit en utilisant Apple Rapporteur de Bug, qui devrait finalement faire son chemin à l'Swift Équipe de Base, ou de Swift, rapporteur de bug. Ces peuvent trouver votre bug trop large ou déjà connu, cependant. L'équipe Swift peut aussi considérer ce que vous cherchez à être une nouvelle fonctionnalité du langage, dans ce cas, vous devriez d'abord vérifier les listes de diffusion.
Mise à jour
En décembre 2016, ce problème a été signalé à la communauté Swift. Le problème n'est toujours marquée comme ouverte avec une priorité moyenne, mais le commentaire suivant a été ajouté:
Ce qui est prévu. Il n'y a aucun moyen d'ajouter la mise en œuvre de la méthode à chaque adoptant, depuis l'extension pourrait être ajoutée après la conformité au protocole. Je suppose que nous pourrions autoriser, si l'extension est dans le même module que le protocole, si.
Depuis votre protocole est dans le même module que votre extension, cependant, vous pourriez être en mesure de le faire dans une future version de Swift.
Mise à jour 2
En février 2017, ce problème a été officiellement fermé comme "Ne pas Faire", l'un des Swift principaux membres de l'Équipe avec le message suivant:
Cela est intentionnel: les extensions de protocole ne peut pas introduire de @objc points d'entrée en raison des limitations de l'Objective-C runtime. Si vous souhaitez ajouter @objc points d'entrée de NSObject, étendre NSObject.
S'étendant NSObject
ou même UIViewController
ne sera pas accomplir exactement ce que vous voulez, mais malheureusement il n'a pas l'air comme il deviendra possible.
Dans le (très) long terme l'avenir, nous pourrions être en mesure d'éliminer la dépendance sur l' @objc
méthodes entièrement, mais que le temps ne sera probablement pas venir de sitôt depuis de Cacao cadres ne sont pas actuellement écrit en Swift (et ne peut pas être jusqu'à ce qu'il a une ABI stable).