weak
les références ne semblent pas fonctionner dans Swift sauf si a protocol
est déclaré comme @objc
, ce que je ne veux pas dans une application Swift pure.
Ce code donne une erreur de compilation ( weak
ne peut pas être appliqué à un type non-classe MyClassDelegate
):
class MyClass {
weak var delegate: MyClassDelegate?
}
protocol MyClassDelegate {
}
J'ai besoin de préfixer le protocole avec @objc
, alors ça marche.
Question: Quelle est la manière Swift «pure» d'accomplir un weak
delegate
?
Réponses:
Vous devez déclarer le type de protocole comme
AnyObject
.En utilisant ,
AnyObject
vous dites que les classes peuvent seulement être conformes à ce protocole, alors que struct ou énumérations ne peut pas.la source
protocol ProtocolNameDelegate: AnyObject
, mais n'a pas d'importance.AnyObject
carclass
il sera déprécié à un moment donné.Réponse supplémentaire
J'étais toujours confus quant à savoir si les délégués devaient être faibles ou non. Récemment, j'ai appris plus sur les délégués et quand utiliser des références faibles, alors permettez-moi d'ajouter quelques points supplémentaires ici pour le bien des futurs téléspectateurs.
Le but de l'utilisation du
weak
mot-clé est d'éviter les cycles de référence forts (conserver les cycles). Des cycles de référence forts se produisent lorsque deux instances de classe ont des références fortes l'une à l'autre. Leurs comptes de référence n'atteignent jamais zéro, ils ne sont donc jamais désalloués.Vous devez utiliser uniquement
weak
si le délégué est une classe. Les structures et énumérations rapides sont des types de valeur (leurs valeurs sont copiées lorsqu'une nouvelle instance est créée), pas des types de référence, de sorte qu'ils ne font pas de cycles de référence forts .weak
les références sont toujours facultatives (sinon vous les utiliseriezunowned
) et utilisent toujoursvar
(paslet
) pour que l'option soit définienil
lorsqu'elle est désallouée.Une classe parent doit naturellement avoir une référence forte à ses classes enfants et donc ne pas utiliser le
weak
mot - clé. Cependant, lorsqu'un enfant veut une référence à son parent, il devrait en faire une référence faible en utilisant leweak
mot - clé.weak
doit être utilisé lorsque vous voulez une référence à une classe que vous ne possédez pas, pas seulement pour un enfant référençant son parent. Lorsque deux classes non hiérarchiques doivent se référencer, choisissez-en une pour être faible. Celui que vous choisissez dépend de la situation. Voir les réponses à cette question pour en savoir plus.En règle générale, les délégués doivent être marqués comme
weak
car la plupart des délégués font référence à des classes qui ne leur appartiennent pas. Cela est tout à fait vrai lorsqu'un enfant utilise un délégué pour communiquer avec un parent. L'utilisation d'une référence faible pour le délégué est ce que la documentation recommande. (Mais voyez ça aussi.)Les protocoles peuvent être utilisés à la fois pour les types de référence (classes) et les types de valeur (structures, énumérations). Donc, dans le cas probable où vous devez affaiblir un délégué, vous devez en faire un protocole uniquement objet. La façon de le faire consiste à ajouter
AnyObject
à la liste d'héritage du protocole. (Dans le passé, vous faisiez cela en utilisant leclass
mot - clé, maisAnyObject
c'est préférable maintenant .)Une étude plus approfondie
La lecture des articles suivants m'a aidé à mieux comprendre cela. Ils discutent également de problèmes connexes tels que le
unowned
mot - clé et les forts cycles de référence qui se produisent lors des fermetures.en relation
la source
AnyObject
est la manière officielle d'utiliser une référence faible dans Swift.D'Apple:
https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Protocols.html#//apple_ref/doc/uid/TP40014097-CH25-ID276
la source
class
déconseillé dans Swift 4.1?Mise à jour: Il semble que le manuel a été mis à jour et l'exemple auquel je faisais référence a été supprimé. Voir la modification de la réponse de @ flainez ci-dessus.
Original: Utiliser @objc est la bonne façon de le faire même si vous n'interopérez pas avec Obj-C. Il garantit que votre protocole est appliqué à une classe et non à une énumération ou une structure. Voir "Vérification de la conformité du protocole" dans le manuel.
la source
le protocole doit être une sous-classe de AnyObject, classe
exemple donné ci-dessous
la source
Apple utilise "NSObjectProtocol" au lieu de "classe".
Cela fonctionne également pour moi et a supprimé les erreurs que je voyais lorsque j'essayais d'implémenter mon propre modèle de délégué.
la source