2016-05-24 2 views
0

J'ai le code ci-dessous et cela fonctionne très bien, mais je m'attendais à la ligne print(john.residence!.numberOfRooms) se bloquer, comme ma variable numberOfRooms a nil valeur et je n'utilise pas forcé wrapping lors du passage de sa valeur en argument à print(). Quelqu'un peut-il s'il vous plaît expliquer pourquoi cela ne déclenche pas une erreur d'exécution et l'impression nil en toute sécurité à la place?L'impression sans propriété force-déballer ne déclenche pas d'erreur d'exécution dans Swift

class Person { 
    var residence: Residence? 
} 

class Residence { 
    var numberOfRooms: Int? 
} 

let john = Person() 

john.residence = Residence() 

print(john.residence!.numberOfRooms) 
+0

Max. Juste pour effacer les choses, vous n'êtes pas forcer déballer sur une valeur nulle. Vous forcez le déballage sur john.residence et il a une valeur. – BangOperator

Répondre

2

Ce que vous faites est appelé en option Enchaînement. Les deux en option Enchaînement et Unwrapping forcé font la même chose, mais:

The main difference is that optional chaining fails gracefully when the optional is nil, whereas forced unwrapping triggers a runtime error when the optional is nil.

“The Swift Programming Language (Swift 2.2).” iBooks. https://itun.es/br/jEUH0.l

vous êtes la force déballant la propriété .residence, ce qui est nil: Il contient une instance Residence, qui a sa .numberOfRooms propriété définie comme nil parce qu'il n'a pas été initialisé. Comme vous ne forcez pas le déballage, aucune erreur n'est donnée, en raison du chaînage optionnel. Essayez la force déballant la propriété .numberOfRooms au lieu d'obtenir une erreur:

print(john.residence!.numberOfRooms!) 

Ou, vous pouvez supprimer la ligne suivante pour définir .residence comme nil:

john.residence = Residence() 

De cette façon john n'a pas .residence, donc essayer de forcer le déballage fera que le compilateur Swift lancera une erreur d'exécution.

+0

Ok, c'est logique, mais une autre question, pourquoi devrais-je utiliser john.residence !.numberOfRooms! quand je peux utiliser john.residence! .numberOfRooms pour obtenir ma valeur. – Max

+0

Lorsque vous utilisez '.numberOfRooms!', Vous déclarez que vous êtes totalement sûr que cette propriété ne renverra pas 'nil'. C'est utile à des fins de débogage, car si vous attendiez qu'une valeur ne soit pas «nil» et qu'elle renvoie «nil», votre programme arrêtera rapidement l'exécution. Cela évitera les erreurs indirectes causées par des valeurs «nil» là où elles ne le devraient pas. –

+0

@Max voir ma réponse mise à jour pour plus d'explications sur ce qui est en option chaînage. –

0

Votre application ne plante pas car vous avez défini la propriété numberOfRooms avec ?. Cela signifie qu'il permettra également la valeur nulle.

Utilisez ! au lieu de ?. Il va certainement planter sur cette déclaration.

print(john.residence!.numberOfRooms) 

Visitez ce lien vous permettant de comprendre la différence entre? et !.
Difference Between ? and ! in Swift Language?

+0

Ce que vous décrivez est un_option_implicitement déballé_, et le problème d'OP fait référence au fait que son code contenant une chaîne _optionnelle ne renvoie pas une erreur d'exécution. –

+0

@Bhumilka john.residence! .numberOfRooms ne plante pas, veuillez vérifier. il afficherait une valeur nulle – Max

+0

@Max Il dit que si vous codez l'initialisation 'Residence' comme' var numberOfRooms: Int! '(en remplaçant **? ** par **! ** ici), cela provoquera la fonction' print' échouer. Cependant, ne l'utilisez pas. Plus sur implicitement déballés optionnels ici: http://stackoverflow.com/questions/24006975/why-create-implicitly-unwrapped-optionals –

-1

I was expecting this line (print(john.residence!.numberOfRooms)) to crash as my numberOfRooms variable has nil value

print() imprime les valeurs à l'intérieur de l'option ou « nul » sans besoin de forcer. Déballer Nous n'avons pas besoin de fournir des types déballés à print(). Même si nous le faisons, nous devons nous assurer qu'il y a une valeur dans l'option.

MISE À JOUR:

Max. Juste pour effacer les choses, vous n'êtes pas forcer le déballage sur une valeur nulle. Vous forcez le déballage sur john.residence et il a une valeur. Vous êtes en train d'imprimer un optionnel. Cela afficherait la «valeur optionnelle» ou «néant». Et si vous vous demandiez pourquoi les options en cours d'impression ne donnent pas d'erreur, c'est parce que print() imprime la valeur optionnelle ou nil. Il ne se bloque pas sur des valeurs nulles.

+0

Faux. 'print (john.residence! .numberOfRooms!)' provoque une erreur d'exécution. L'erreur n'est pas renvoyée dans son code en raison de l'échec de la chaîne _optional chaining_, ce qui n'est pas dû à la façon dont 'print()' fonctionne. –

+0

@TiagoMarinho Peut-être que j'ai mal compris la question. Il demandait pourquoi "numberOfRooms" avec une valeur nulle ne plante pas. Même j'ai eu cette pensée plus tôt que l'accès optionnel avec une valeur nulle donne une erreur. Et l'accès d'impression l'option sans donner d'erreurs. La raison en est que l'impression gère très bien les deux cas. Et j'avais répondu à cette question, "Pourquoi imprimer ne donne pas d'erreur lors de l'impression nil facultatif?". Dans ce contexte, aucune de mes affirmations est fausse. – BangOperator

+0

Et c'est la raison pour laquelle je n'avais pas ajouté "et j'utilise le déballage forcé par un point d'exclamation" dans la citation comme il était inutile dans le contexte j'ai compris la question. – BangOperator