Quelle est la différence entre un protocole étendu à partir de AnyObject et un protocole de classe uniquement?

Tant cette déclaration

protocol SomeProtocol : AnyObject { } 

et cette déclaration

 protocol SomeProtocol : class { } 

semblent faire en sorte que seules les classes puissent se conformer à ce protocole (c.-à-d. que les instances du protocole soient des références à des objects), et ne pas avoir d’autres effets.

Y a-t-il une différence entre eux? Doit-on être préféré à l’autre? Sinon, pourquoi y a-t-il deux façons de faire la même chose?

J’utilise la dernière version de Xcode 6.3.1.

En ce qui concerne la réponse https://forums.swift.org/t/class-only-protocols-class-vs-anyobject/11507/4 , cette réponse est obsolète. Ces mots sont les mêmes maintenant.

PÉRIMÉ

Mise à jour: Après consultation avec les pouvoirs en place , les deux définitions sont supposées être équivalentes, AnyObject étant utilisé en tant que remplaçant pendant la fin de la class . Dans le futur, ce dernier évitera les premiers mais, pour le moment, ils présentent quelques différences mineures.

La différence réside dans la sémantique des déclarations @objc . Avec AnyObject , on s’attend à ce que les classes conformes soient ou non des objects Objective-C appropriés, mais le langage les traite de toute façon (en ce sens que vous perdez parfois la dissortingbution statique). La AnyObject est que vous pouvez traiter un AnyObject et al. contrainte de protocole comme moyen de demander des fonctions membres @objc comme indiqué dans l’exemple de la documentation pour AnyObject dans la STL:

 import Foundation class C { @objc func getCValue() -> Int { return 42 } } // If x has a method @objc getValue()->Int, call it and // return the result. Otherwise, return nil. func getCValue1(x: AnyObject) -> Int? { if let f: ()->Int = x.getCValue { // <=== return f() } return nil } // A more idiomatic implementation using "optional chaining" func getCValue2(x: AnyObject) -> Int? { return x.getCValue?() // <=== } // An implementation that assumes the required method is present func getCValue3(x: AnyObject) -> Int { // <=== return x.getCValue() // x.getCValue is implicitly unwrapped. // <=== } 

Le même exemple tombe immédiatement si vous changez cela en un protocole de class :

 import Foundation protocol SomeClass : class {} class C : SomeClass { @objc func getCValue() -> Int { return 42 } } // If x has a method @objc getValue()->Int, call it and // return the result. Otherwise, return nil. func getCValue1(x: SomeClass) -> Int? { if let f: ()->Int = x.getCValue { // <=== SomeClass has no member 'getCValue' return f() } return nil } // A more idiomatic implementation using "optional chaining" func getCValue2(x: SomeClass) -> Int? { return x.getCValue?() // <=== SomeClass has no member 'getCValue' } // An implementation that assumes the required method is present func getCValue3(x: SomeClass) -> Int { // <=== return x.getCValue() // <=== SomeClass has no member 'getCValue' } 

Il semble donc que la class soit une version plus conservasortingce d' AnyObject qui devrait être utilisée lorsque vous vous souciez uniquement de la sémantique de référence et non de la recherche dynamic de membres ou du pontage Objective-C.

AnyObject est un protocole auquel toutes les classes se conforment implicitement ( source ). Je dirais donc qu’il n’y a pas de différence: vous pouvez soit utiliser la contrainte de classe.

Dans le Swift Programming Language (Swift 4) , sous la section Protocoles uniquement . Il a seulement mentionné AnyObject , mais pas la class .

Vous pouvez limiter l’adoption du protocole aux types de classe (et non aux structures ou énumérations) en ajoutant le protocole AnyObject à la liste d’inheritance d’un protocole.

 protocol SomeClassOnlyProtocol: AnyObject, SomeInheritedProtocol { // class-only protocol definition goes here } 

Pour cette raison, je vous suggère d’utiliser AnyObject plutôt que la class pour un nouveau code ou un nouveau projet. En dehors de cela, je ne vois aucune différence évidente entre eux.

Je me suis mal exprimé auparavant. @MartinR devrait vraiment répondre à cela, car c’est lui qui m’a corrigé et fourni les informations correctes.

La vraie différence est qu’un protocole avec le qualificatif de classe ne peut être appliqué qu’à une classe, pas à un struct ou à un enum.

Martin, pourquoi tu ne réponds pas et le PO peut accepter ta réponse?

Si vous ouvrez l’aide (Alt-clic) dans Xcode 9 pour class une ligne telle que le protocol P: class {} , vous obtiendrez typealias AnyObject .

Ainsi, le code compilé (dans Swift 4) sera le même que vous AnyObject le protocole à la class ou à AnyObject .

Cela dit, il y a aussi la question du style et des options futures – une future version de Swift pourrait vouloir traiter la class et AnyObject différemment de manière subtile, même si ce n’est pas le cas actuellement.