Comment Swift IF LET est-il évalué?


87

J'ai vu ce code sur le site Swift et divers articles ici et j'essaie de comprendre les bases. Comment cette ligne est-elle évaluée?

if let name = optionalName {

Je suis confus car ce n'est pas le nom == nom facultatif, il attribue la valeur, alors comment ce rapport est-il vrai et pourquoi n'est-il pas vrai lorsque vous remplacez par john appleseed par nil, car il sera toujours égal?

var optionalName: String? = "John Appleseed"
var greeting = "Hello!"
if let name = optionalName {
    greeting = "Hello, \(name)"
}

10
Recherche "liaison optionnelle" dans la documentation Swift ...
Martin R

3
Un examen détaillé des options sur dev.iachieved.it/iachievedit/?p=314 , la if letsyntaxe est connue sous le nom de liaison facultative.
Joe le

Réponses:


101

Essentiellement, la ligne dit: "si vous pouvez laisser la nouvelle variable nameégaler la version non facultative de optionalName, faites ce qui suit avec". Comme Martin l'a souligné, cela s'appelle la liaison facultative .

Le seul but de celui-ci est de tester si une variable facultative contient une valeur réelle et de lier le formulaire non facultatif à une variable temporaire. C'est le moyen le plus sûr de "déballer" une option ou, en d'autres termes, d'accéder à la valeur contenue dans l'option. Il ne s'agit en aucun cas de test d'égalité d'aucune sorte. Il ne teste que l'existence d'une valeur dans un optionnel.


2
J'aurai une lecture de ça quand j'y arriverai, je suis juste au début de l'intro rapide et ça ne l'explique pas. votre explication est parfaitement logique, merci.
DeadZero

1
Pourquoi ne devrions-nous pas utiliser "! =" Au lieu de "if let" pour vérifier si la variable optionnelle a une valeur comme - if optionalName! = Nil {salutation = "Hello, (name)"}
Nuibb

4
@Nuibb car lors de l'utilisation, if letnous lions la valeur à une variable non facultative ( namedans cet exemple). Votre exemple ne serait pas compilé car il n'y a plus de variable appelée name. Si vous avez changé votre exemple pour l'utiliser, optionalNameil s'imprimerait comme Hello, Optional("John Appleseed"). Vous pouvez utiliser le déballage forcé après avoir vérifié la valeur nulle, Hello, \(optionalName!)mais c'est juste plus sujet aux erreurs si vous déplacez cette section de code quelque part sans vérification.
tirage

29

Un optionnel est défini ou non défini (ni nul ni nul) ... nous laissant avec une décision importante. "Comment devons-nous écrire notre code pour qu'il puisse fonctionner correctement pour les deux états?". La façon dont nous déballons l'option est ce qui en décide pour nous.

Il existe plusieurs approches que vous pouvez utiliser pour contrer une option non définie.

  • Crash!
  • La valeur par défaut est quelque chose - si elle n'a pas été définie.
  • Échouer gracieusement, c'est-à-dire ne rien faire, mais aussi si la valeur a été définie, attribuez-la.
  • Échouer gracieusement, c'est-à-dire ne rien faire, mais si la valeur a été définie ... faire quelque chose (c'est juste plus qu'une simple affectation).

Voici les 4 approches


L'utilisation du déballage forcé plantera si vous n'avez pas de valeur. Vous voudrez faire ceci si avoir cette valeur est d'une importance vitale, par exemple le titre d'un film (chaque film DOIT avoir un nom). !est utilisé pour le déballage forcé.

movieTitle = movie.title!

L'utilisation de la fusion nil est une autre façon de vous donner plus de contrôle , ce qui signifie qu'elle ne plantera pas si la valeur n'est pas définie, ni ne `` ne la définira rien '' si elle n'est pas définie ... cela ferait ce que vous lui dites. pour faire, par exemple, il faudrait par défaut / définir le nom du film sur untitled_movie s'il n'y avait pas de nom défini. ??est utilisé pour une fusion nulle.

var movieTitle = movie.title ?? "untitled_Movie"

L'utilisation du chaînage facultatif ne fera rien si vous n'avez pas de valeur et définira la valeur si vous avez une valeur. Vous faites cela pour quelque chose dont la valeur définie n'est pas d'une importance vitale, par exemple pour le nom de l'agent de votre acteur . ?est utilisé pour le chaînage facultatif.

let agent = movie.leadActor?.agent //would not crash if you don't have a lead actor (optional chaining)
let agent = movie.leadActor!.agent //would crash if you don't have a lead Actor (forced wrapping)  

Utiliser if-let(ou guardqui sont deux types différents de liaison facultative ) vous donnera plus de contrôle , il ne plantera pas si la valeur n'est pas définie. Si la valeur est définie, vous pouvez faire quelque chose. S'il n'est pas défini, vous pouvez ajouter une elsedéclaration.

if let supportingActor = movie.supportingActor{
print(" The supporting actor is \(supportingActor)}

C'est le moyen le plus couramment utilisé pour déballer, car le déballage forcé est quelque peu déconseillé. Pour plus d'informations sur les raisons pour lesquelles il est déconseillé, voir ici . Pour une bonne comparaison entre guardet if-letvoirguard vs. if-let


Note latérale:

La liaison facultative et le chaînage facultatif sont couramment utilisés ensemble:

if let agent = movie.leadActor?.agent {
ContactInfo = agent.phoneNumber
} // if-let is the optional *binding* part, the movie dot leadActor dot is the optional *chaining*
 

Pourquoi le déballage forcé serait-il déconseillé étant donné une situation où movieTitle ne peut jamais être autre chose qu'une chaîne, et toutes les chaînes sont valides pour movieTitle? (et je ne veux pas de "film sans titre" Je veux "") Le déballage forcé est le seul bon moyen pour cette situation, ce serait bien si vous pouviez supprimer la partie qui dit "le déballage forcé est quelque peu découragé" car c'est une fausse info .
Andy

Supposons que vous passiez un appel réseau et qu'un développeur de l'équipe serveur ait pris une mauvaise décision et oublié d'envoyer le titre du film. Voulez-vous que votre application plante en production? Ou simplement écrire un titre inconnu? En fait, certains films sur IMDb n'ont pas de titre :). De plus, le déballage forcé implique que vous n'avez effectué aucune journalisation ou assertion. C'est mauvais. Parce que vous ne saurez pas quelle était la cause profonde.
Honey

C'est un argument d'homme de paille, je n'ai jamais dit "toujours utiliser le déballage forcé". Ce n'est pas parce que vous ne devriez pas utiliser le déballage forcé dans votre exemple que le déballage forcé est déconseillé à chaque exemple. Je vous ai donné un scénario où le déballage forcé est la seule bonne solution parmi les quatre que vous avez présentées. Pouvez-vous fournir une meilleure solution au scénario énoncé dans mon commentaire précédent? Sinon, pensez à modifier votre commentaire sur "le déballage forcé est quelque peu découragé" car il n'est pas quelque peu découragé sans tenir compte du contexte.
Andy

Si vous réglez par défaut quelque chose sur "", ce n'est plus une option
Chérie,

Par exemple, cette valeur "" provient de la propriété text d'une instance UILabel créée dans le storyboard, elle est facultative car elle peut être nulle si vous la créez dynamiquement, mais ici vous ne la créez pas dynamiquement, elle contiendra donc toujours une valeur de chaîne . N'allez-vous pas utiliser le déballage forcé dans ce cas, au lieu de cela, vous déballerez avec if-let et fourniriez une valeur identique à sa valeur par défaut ""? Vous pouvez, mais c'est inutile, inutile et verbeux. Et si vous utilisez une bibliothèque HTTP qui renverra toujours un dictionnaire même s'il s'agit d'une erreur. Cela dépend du contexte.
Andy

4

La syntaxe if accepte 2 conditions différentes. Le second, une liaison facultative, n'est pas un booléen. C'est déroutant, comme vous pouvez l'écrire:

if let name = optionalName {

mais non

if (let name = optionalName) {

Documentation Apple (référence Swift):

La valeur de la condition doit être de type Boolou de type ponté Bool. La condition peut également être une déclaration de liaison facultative, comme indiqué dans Liaison facultative .


3

if ne prend que les expressions booléennes, à part cela, cela générerait une erreur, donc cet extrait de code disant

if let name = optionalName {

}else{

}

si optionalName est nul, la condition est fausse et l'instruction else s'exécutera. Cependant, si optionalName a une valeur, la valeur optionnelle est déroulée / affectée dans la variable constante, c'est-à-dire name.


1

Chaque fois que vous travaillez avec des références faibles, des types optionnels, il serait préférable d'utiliser si vous permettez de protéger votre code et d'éviter les plantages Voici les exemples

var middleName :String? = "some thing"
if let isExistsMiddleName = middleName {
// do some thing here
} else {
// no middle name
}
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.