31 votes

"Cannot assign value of type 'String' to type 'AnyObject?'", Swift 3, Xcode 8 beta 6

Un morceau de code assez simple

var dict: [String: AnyObject] = [:]
dict["key"] = "value"

génère l'erreur de compilation suivante

Cannot assign value of type 'String' to type 'AnyObject?'

De simples vérifications de type me disent que String est AnyObject

"value" is AnyObject // returns true

Je pourrais changer AnyObject a Any et tout fonctionnerait

var dict: [String: Any] = [:]
dict["key"] = "value"

mais je veux comprendre pourquoi je reçois l'erreur ? Est-ce que String plus du tout AnyObject ? Ou s'agit-il d'un bug ?

38voto

Rob Napier Points 92148

En b6, String ne fait plus le pont comme par magie avec NSString. String n'est pas une classe ; c'est un struct. Vous devez faire le pont à la main :

dict["key"] = "value" as AnyObject

Le fait que is semble toujours faire le pont est probablement un bogue et devrait être signalé.

Il va sans dire que [String: AnyObject] y [String: Any] doit être utilisé le moins possible dans votre code.

(Assurez-vous de suivre le lien fourni par Hamish dans les commentaires ci-dessous).

4voto

dfri Points 11222

Je vais compléter La réponse de @RobNapier avec certaines sources officielles.


La suppression des mécanismes de pontage implicite a été acceptée dans la proposition d'évolution de Swift suivante, à mettre en œuvre pour Swift 3

Auparavant, des conversions implicites étaient disponibles de certains types natifs de Swift à types Objective-C associés (types Swift conformes au protocole privé _ObjectiveCBridgeable par exemple, de manière native Int , String , )

Pour cette raison, nous avons décidé de faire un compromis. Nous exiger des moulages de pontage explicites lors de la conversion de une passerelle Objective-C type à son type de valeur Swift associé (par exemple, NSString -> String), mais pas l'inverse .

... [De SE-0072]

Avec Swift 3, ces mécanismes de conversion implicite ne seront plus disponibles.

Avec l'introduction des génériques en Objective-C l'année dernière, ainsi qu'avec toutes les superbes améliorations apportées à l'importation d'API pour Swift 3. 3, je pense qu'il est temps que nous nous penchions à nouveau sur l'achèvement de ce travail.

...

Je propose que nous éliminer complètement les conversions implicites de pontage dans . Cela signifie que certains utilisateurs pourraient devoir introduire plus de casts explicites dans leur code, mais nous supprimerions un autre cas particulier du système de types de Swift et serions en mesure de simplifier davantage le système. spécial du système de types de Swift et nous pourrions simplifier encore davantage la compilateur.

...

Le code qui reposait auparavant sur des conversions implicites entre Swift et leur type Objective-C associé. va maintenant nécessitera une coercition manuelle via un as moulage .

Enfin, les notes de publication de Xcode 8 beta 6 (login required) indique que cette proposition a maintenant été mise en œuvre pour la bêta 6 :

Nouveau dans Xcode 8 beta 6 - Compilateur Swift : Le langage Swift

...

  • Les conversions de pont ne sont plus implicites. La conversion d'un type de valeur Swift vers son objet correspondant peut être forcée avec as . Par exemple : string as NSString . Toute valeur de Swift peut également être convertie en sa représentation boxed id avec as AnyObject . (SE-0072)

W.r.t. new "id en boîte" permettant la conversion explicite de toute valeur Swift en AnyObject voir, par exemple, le fil de discussion suivant :

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X