Qu'est-ce qu'une valeur facultative dans Swift?

267

À partir de la documentation d'Apple :

Vous pouvez utiliser ifet letensemble pour travailler avec des valeurs qui pourraient être manquantes. Ces valeurs sont représentées comme des options. Une valeur facultative contient une valeur ou contient nilpour indiquer que la valeur est manquante. Écrivez un point d'interrogation ( ?) après le type d'une valeur pour marquer la valeur comme facultative.

Pourquoi voudriez-vous utiliser une valeur facultative?

Tim Vermeulen
la source
1
Facultatif peut également être considéré comme une implémentation de la monade Option / Peut-être . Ce blog ici fait un bon travail pour essayer d'expliquer ce qui est autrement un concept difficile.
StuartLC
tldr: "Swift a besoin que vous sachiez clairement quand une valeur peut être manquante et quand elle est garantie d'exister." de l' excellente réponse
jonatan

Réponses:

532

Une option dans Swift est un type qui peut contenir une valeur ou aucune valeur. Les options sont écrites en ajoutant un ?à n'importe quel type:

var name: String? = "Bertie"

Les options (avec les génériques) sont l'un des concepts Swift les plus difficiles à comprendre. En raison de la façon dont ils sont écrits et utilisés, il est facile de se faire une mauvaise idée de ce qu'ils sont. Comparez l'option facultative ci-dessus à la création d'une chaîne normale:

var name: String = "Bertie" // No "?" after String

D'après la syntaxe, il semble qu'une chaîne facultative soit très similaire à une chaîne ordinaire. Ce n'est pas. Une chaîne facultative n'est pas une chaîne avec un paramètre "facultatif" activé. Ce n'est pas une variété spéciale de String. Une chaîne et une chaîne facultative sont des types complètement différents.

Voici la chose la plus importante à savoir: une option est une sorte de conteneur. Une chaîne facultative est un conteneur qui peut contenir une chaîne. Un Int facultatif est un conteneur qui peut contenir un Int. Considérez une option comme une sorte de colis. Avant de l'ouvrir (ou "dérouler" dans la langue des options), vous ne saurez pas s'il contient quelque chose ou rien.

Vous pouvez voir comment les options sont implémentées dans la bibliothèque standard de Swift en tapant "Facultatif" dans n'importe quel fichier Swift et en cliquant dessus. Voici la partie importante de la définition:

enum Optional<Wrapped> {
    case none
    case some(Wrapped)
}

Facultatif est juste un enumqui peut être l'un des deux cas: .noneou .some. Si c'est le cas .some, il y a une valeur associée qui, dans l'exemple ci-dessus, serait le String"Bonjour". Une option utilise Generics pour donner un type à la valeur associée. Le type d'une chaîne facultative ne l'est pas String, c'est Optionalou plus précisément Optional<String>.

Tout ce que Swift fait avec les options est magique pour rendre la lecture et l'écriture de code plus fluide. Malheureusement, cela obscurcit la façon dont cela fonctionne réellement. Je vais passer en revue certaines des astuces plus tard.

Remarque: je vais beaucoup parler des variables facultatives, mais c'est bien de créer des constantes facultatives aussi. Je marque toutes les variables avec leur type pour faciliter la compréhension des types de types en cours de création, mais vous n'avez pas à le faire dans votre propre code.


Comment créer des options

Pour créer une option, ajoutez un ?après le type que vous souhaitez encapsuler. Tout type peut être facultatif, même vos propres types personnalisés. Vous ne pouvez pas avoir d'espace entre le type et le ?.

var name: String? = "Bob" // Create an optional String that contains "Bob"
var peter: Person? = Person() // An optional "Person" (custom type)

// A class with a String and an optional String property
class Car {
var modelName: String // must exist
var internalName: String? // may or may not exist
}

Utilisation des options

Vous pouvez comparer un facultatif pour nilvoir s'il a une valeur:

var name: String? = "Bob"
name = nil // Set name to nil, the absence of a value
if name != nil {
    print("There is a name")
}
if name == nil { // Could also use an "else"
    print("Name has no value")
}

C'est un peu déroutant. Cela implique qu'une option est soit une chose, soit une autre. C'est nul ou c'est "Bob". Ce n'est pas vrai, le facultatif ne se transforme pas en quelque chose d'autre. Le comparer à nil est une astuce pour rendre le code plus facile à lire. Si un facultatif est égal à zéro, cela signifie simplement que l'énumération est actuellement définie sur .none.


Seuls les optionnels peuvent être nuls

Si vous essayez de définir une variable non facultative sur nil, vous obtiendrez une erreur.

var red: String = "Red"
red = nil // error: nil cannot be assigned to type 'String'

Une autre façon de voir les options est en complément des variables Swift normales. Ils sont la contrepartie d'une variable dont la valeur est garantie. Swift est un langage prudent qui déteste l'ambiguïté. La plupart des variables sont définies comme non optionnelles, mais parfois ce n'est pas possible. Par exemple, imaginez un contrôleur de vue qui charge une image à partir d'un cache ou du réseau. Il peut ou non avoir cette image au moment de la création du contrôleur de vue. Il n'y a aucun moyen de garantir la valeur de la variable image. Dans ce cas, vous devrez le rendre facultatif. Il commence au fur nilet à mesure que l'image est récupérée, le facultatif obtient une valeur.

L'utilisation d'une option révèle l'intention du programmeur. Par rapport à Objective-C, où n'importe quel objet peut être nul, Swift a besoin que vous sachiez clairement quand une valeur peut être manquante et quand elle est garantie d'exister.


Pour utiliser une option, vous la "déballez"

Une option Stringne peut pas être utilisée à la place d'une réelle String. Pour utiliser la valeur encapsulée dans une option, vous devez la déballer. Le moyen le plus simple de déballer une option est d'ajouter un !après le nom facultatif. C'est ce qu'on appelle le "déballage forcé". Il renvoie la valeur à l'intérieur de l'option (comme le type d'origine) mais si l'option est nil, elle provoque un crash d'exécution. Avant de déballer, vous devez vous assurer qu'il y a une valeur.

var name: String? = "Bob"
let unwrappedName: String = name!
print("Unwrapped name: \(unwrappedName)")

name = nil
let nilName: String = name! // Runtime crash. Unexpected nil.

Vérification et utilisation d'une option

Parce que vous devez toujours vérifier zéro avant de déballer et d'utiliser une option, c'est un modèle courant:

var mealPreference: String? = "Vegetarian"
if mealPreference != nil {
    let unwrappedMealPreference: String = mealPreference!
    print("Meal: \(unwrappedMealPreference)") // or do something useful
}

Dans ce modèle, vous vérifiez qu'une valeur est présente, puis lorsque vous êtes sûr qu'elle l'est, vous forcez à la dérouler dans une constante temporaire à utiliser. Parce que c'est une chose courante à faire, Swift propose un raccourci en utilisant "if let". C'est ce qu'on appelle la "liaison facultative".

var mealPreference: String? = "Vegetarian"
if let unwrappedMealPreference: String = mealPreference {
    print("Meal: \(unwrappedMealPreference)") 
}

Cela crée une constante temporaire (ou variable si vous remplacez letpar var) dont la portée se trouve uniquement entre les accolades de l'if. Parce que devoir utiliser un nom tel que "unwrappedMealPreference" ou "realMealPreference" est un fardeau, Swift vous permet de réutiliser le nom de variable d'origine, en créant un nom temporaire dans la portée du support

var mealPreference: String? = "Vegetarian"
if let mealPreference: String = mealPreference {
    print("Meal: \(mealPreference)") // separate from the other mealPreference
}

Voici du code pour démontrer qu'une variable différente est utilisée:

var mealPreference: String? = "Vegetarian"
if var mealPreference: String = mealPreference {
    print("Meal: \(mealPreference)") // mealPreference is a String, not a String?
    mealPreference = "Beef" // No effect on original
}
// This is the original mealPreference
print("Meal: \(mealPreference)") // Prints "Meal: Optional("Vegetarian")"

La liaison facultative fonctionne en vérifiant si l'option est égale à zéro. Si ce n'est pas le cas, il décompresse l'option dans la constante fournie et exécute le bloc. Dans Xcode 8.3 et versions ultérieures (Swift 3.1), essayer d'imprimer une option comme celle-ci entraînera un avertissement inutile. Utilisez les options debugDescriptionpour le désactiver:

print("\(mealPreference.debugDescription)")

À quoi servent les options?

Les options ont deux cas d'utilisation:

  1. Des choses qui peuvent échouer (je m'attendais à quelque chose mais je n'ai rien eu)
  2. Des choses qui ne sont rien maintenant mais qui pourraient être quelque chose plus tard (et vice-versa)

Quelques exemples concrets:

  • Une propriété qui peut être là ou pas là, comme middleNameou spousedans une Personclasse
  • Une méthode qui peut retourner une valeur ou rien, comme la recherche d'une correspondance dans un tableau
  • Une méthode qui peut renvoyer un résultat ou obtenir une erreur et ne rien retourner, comme essayer de lire le contenu d'un fichier (qui renvoie normalement les données du fichier) mais le fichier n'existe pas
  • Propriétés de délégué, qui ne doivent pas toujours être définies et sont généralement définies après l'initialisation
  • Pour les weakpropriétés dans les classes. La chose sur laquelle ils pointent peut être réglée nilà tout moment
  • Une grande ressource qui pourrait devoir être libérée pour récupérer de la mémoire
  • Lorsque vous avez besoin d'un moyen de savoir quand une valeur a été définie (données non encore chargées> les données) au lieu d'utiliser des données distinctes Boolean

Les optionnels n'existent pas dans Objective-C mais il existe un concept équivalent, renvoyant nil. Les méthodes qui peuvent renvoyer un objet peuvent retourner nil à la place. Cela signifie "l'absence d'un objet valide" et est souvent utilisé pour dire que quelque chose s'est mal passé. Il ne fonctionne qu'avec des objets Objective-C, pas avec des primitives ou des types C de base (énumérations, structures). Objective-C avait souvent des types spécialisés pour représenter l'absence de ces valeurs ( NSNotFoundce qui est vraiment NSIntegerMax, kCLLocationCoordinate2DInvalidpour représenter une coordonnée invalide, -1ou une valeur négative est également utilisée). Le codeur doit connaître ces valeurs spéciales, elles doivent donc être documentées et apprises pour chaque cas. Si une méthode ne peut pas prendre nilcomme paramètre, cela doit être documenté. Dans Objective-C,nilétait un pointeur tout comme tous les objets étaient définis comme des pointeurs, mais nilpointait vers une adresse spécifique (zéro). Dans Swift, nilest un littéral qui signifie l'absence d'un certain type.


Comparé à nil

Vous pouviez utiliser n'importe quelle option en tant que Boolean:

let leatherTrim: CarExtras? = nil
if leatherTrim {
    price = price + 1000
}

Dans les versions plus récentes de Swift, vous devez utiliser leatherTrim != nil. Pourquoi est-ce? Le problème est qu'un Booleanpeut être enveloppé dans une option. Si vous avez Booleancomme ça:

var ambiguous: Boolean? = false

il a deux sortes de "faux", un où il n'y a pas de valeur et un où il a une valeur mais la valeur est false. Swift déteste l'ambiguïté, vous devez donc toujours vérifier une option nil.

Vous vous demandez peut-être à quoi Booleansert une option ? Comme pour les autres options, l' .noneétat pourrait indiquer que la valeur est encore inconnue. Il peut y avoir quelque chose à l'autre bout d'un appel réseau qui prend un certain temps à interroger. Les booléens facultatifs sont également appelés « booléens à trois valeurs »


Astuces rapides

Swift utilise quelques astuces pour permettre aux options de fonctionner. Considérez ces trois lignes de code optionnel ordinaire;

var religiousAffiliation: String? = "Rastafarian"
religiousAffiliation = nil
if religiousAffiliation != nil { ... }

Aucune de ces lignes ne doit être compilée.

  • La première ligne définit une chaîne facultative à l'aide d'un littéral chaîne, deux types différents. Même si c'était un, Stringles types sont différents
  • La deuxième ligne définit une chaîne facultative sur nil, deux types différents
  • La troisième ligne compare une chaîne facultative à nil, deux types différents

Je vais passer en revue certains des détails d'implémentation des options qui permettent à ces lignes de fonctionner.


Création d'une option

Utiliser ?pour créer une option est du sucre syntaxique, activé par le compilateur Swift. Si vous voulez le faire à long terme, vous pouvez créer une option comme celle-ci:

var name: Optional<String> = Optional("Bob")

Cela appelle Optionalle premier initialiseur de, public init(_ some: Wrapped)qui déduit le type associé facultatif à partir du type utilisé entre parenthèses.

La façon encore plus longue de créer et de définir une option:

var serialNumber:String? = Optional.none
serialNumber = Optional.some("1234")
print("\(serialNumber.debugDescription)")

Définir une option sur nil

Vous pouvez créer une option sans valeur initiale ou en créer une avec la valeur initiale de nil(les deux ont le même résultat).

var name: String?
var name: String? = nil

Permettre aux optionnels d'être égaux nilest activé par le protocole ExpressibleByNilLiteral(précédemment nommé NilLiteralConvertible). L'option est créé avec la Optionaldeuxième initialiseur de », public init(nilLiteral: ()). Les docs disent que vous ne devriez pas utiliser ExpressibleByNilLiteralquoi que ce soit, sauf les options, car cela changerait la signification de nil dans votre code, mais il est possible de le faire:

class Clint: ExpressibleByNilLiteral {
    var name: String?
    required init(nilLiteral: ()) {
        name = "The Man with No Name"
    }
}

let clint: Clint = nil // Would normally give an error
print("\(clint.name)")

Le même protocole vous permet de définir un optionnel déjà créé sur nil. Bien que ce ne soit pas recommandé, vous pouvez utiliser directement l'initialiseur littéral nil:

var name: Optional<String> = Optional(nilLiteral: ())

Comparaison d'une option à nil

Les options définissent deux opérateurs spéciaux "==" et "! =", Que vous pouvez voir dans la Optionaldéfinition. La première ==vous permet de vérifier si une option est égale à zéro. Deux options différentes qui sont définies sur .none seront toujours égales si les types associés sont les mêmes. Lorsque vous comparez à zéro, Swift crée en arrière-plan une option du même type associé, définie sur .none, puis l'utilise pour la comparaison.

// How Swift actually compares to nil
var tuxedoRequired: String? = nil
let temp: Optional<String> = Optional.none
if tuxedoRequired == temp { // equivalent to if tuxedoRequired == nil
    print("tuxedoRequired is nil")
}

Le deuxième ==opérateur vous permet de comparer deux options. Les deux doivent être du même type et ce type doit être conforme Equatable(le protocole qui permet de comparer les choses avec l'opérateur régulier "=="). Swift (vraisemblablement) déballe les deux valeurs et les compare directement. Il gère également le cas où l'un ou les deux options sont .none. Notez la distinction entre comparer au nillittéral.

De plus, il vous permet de comparer n'importe quel Equatabletype à un habillage optionnel de ce type:

let numberToFind: Int = 23
let numberFromString: Int? = Int("23") // Optional(23)
if numberToFind == numberFromString {
    print("It's a match!") // Prints "It's a match!"
}

Dans les coulisses, Swift encapsule le non-optionnel comme optionnel avant la comparaison. Cela fonctionne aussi avec les littéraux ( if 23 == numberFromString {)

J'ai dit qu'il y a deux ==opérateurs, mais il y a en fait un troisième qui vous permet de mettre nilsur le côté gauche de la comparaison

if nil == name { ... }

Options de dénomination

Il n'y a pas de convention Swift pour nommer les types facultatifs différemment des types non facultatifs. Les gens évitent d'ajouter quelque chose au nom pour montrer qu'il s'agit d'un type facultatif (comme "optionalMiddleName" ou "possibleNumberAsString") et laisser la déclaration montrer qu'il s'agit d'un type facultatif. Cela devient difficile lorsque vous voulez nommer quelque chose pour contenir la valeur d'une option. Le nom "middleName" implique qu'il s'agit d'un type String, donc lorsque vous en extrayez la valeur, vous pouvez souvent vous retrouver avec des noms comme "actualMiddleName" ou "unwrappedMiddleName" ou "realMiddleName". Utilisez la liaison facultative et réutilisez le nom de la variable pour contourner ce problème.


La définition officielle

Extrait de "The Basics" dans le langage de programmation Swift :

Swift introduit également des types facultatifs, qui gèrent l'absence de valeur. Les optionnels disent «il y a une valeur, et elle est égale à x» ou «il n'y a pas du tout de valeur». Les options sont similaires à l'utilisation de nil avec des pointeurs dans Objective-C, mais elles fonctionnent pour tout type, pas seulement pour les classes. Les options sont plus sûres et plus expressives que les pointeurs nuls dans Objective-C et sont au cœur de nombreuses fonctionnalités les plus puissantes de Swift.

Les options sont un exemple du fait que Swift est un langage sûr de type. Swift vous aide à être clair sur les types de valeurs avec lesquelles votre code peut fonctionner. Si une partie de votre code attend une chaîne, la sécurité de type vous empêche de lui transmettre un Int par erreur. Cela vous permet de détecter et de corriger les erreurs le plus tôt possible dans le processus de développement.


Pour terminer, voici un poème de 1899 sur les options:

Hier, dans l'escalier,
j'ai rencontré un homme qui n'était pas là
Il n'était plus là aujourd'hui
Je souhaite, je souhaite qu'il s'en aille

Antigonish


Plus de ressources:

nevan king
la source
5
@KaanDedeoglu Malheureusement, Steve est vraiment une option. Il était ici et maintenant il ne l'est plus.
nevan king
19
if myStringne compile plus. Vous en avez besoin if myString != nil. Voir documentation .
Pang
5
explication la meilleure et la plus claire pour? et ! utiliser dans Swift que j'ai trouvé sur le web. merci
mindbomb
2
mateo explique en détail les options, atteignant en profondeur et des exemples simples.
iluvatar_GR
4
Merci pour cette explication, elle est beaucoup plus claire que la propre documentation d'Apple.
yesthisisjoe
16

Prenons l'exemple d'un NSError, s'il n'y a pas d'erreur retournée, vous voudriez rendre facultatif le retour de Nil. Il ne sert à rien de lui attribuer une valeur s'il n'y a pas d'erreur.

var error: NSError? = nil

Cela vous permet également d'avoir une valeur par défaut. Vous pouvez donc définir une méthode par défaut si la fonction ne reçoit rien

func doesntEnterNumber(x: Int? = 5) -> Bool {
    if (x == 5){
        return true
    } else {
        return false
    }
}
John Riselvato
la source
La phrase «Si c'est nul, le résultat de toute expression avec ça est nul aussi» est tout simplement fausse. func isNil<T>(t: T?) -> Bool { return t == nil }retournera truemême s'il existe une valeur facultative qui se trouve nildans l'expression.
retour vrai
Échantillon de code incroyablement mauvais. Ne pourriez-vous pas penser à quelque chose de mieux? Pourquoi pas simplement return x == 5? Quelle est la particularité de 5?
Atomosk
Non, il y a 2 ans, je ne pouvais pas penser à quelque chose de mieux. Aujourd'hui oui, mais cela fait-il passer le message? Oui. Merci pour l'entrée @Atomosk, c'est vraiment utile.
John Riselvato
12

Vous ne pouvez pas avoir une variable qui pointe nildans Swift - il n'y a pas de pointeurs et pas de pointeurs nuls. Mais dans une API, vous voulez souvent pouvoir indiquer soit un type spécifique de valeur, soit un manque de valeur - par exemple ma fenêtre a-t-elle un délégué, et si oui, qui est-ce? Les options sont le moyen sûr de type et de mémoire de Swift pour ce faire.

rickster
la source
11

J'ai fait une courte réponse, qui résume la plupart des éléments ci-dessus, pour nettoyer l'incertitude qui était dans ma tête en tant que débutant:

Contrairement à Objective-C, aucune variable ne peut contenir zéro dans Swift, donc le type de variable facultatif a été ajouté (variables suffixées par "?"):

    var aString = nil //error

La grande différence est que les variables facultatives ne stockent pas directement les valeurs (comme le feraient les variables Obj-C normales), elles contiennent deux états : " a une valeur " ou " a nil ":

    var aString: String? = "Hello, World!"
    aString = nil //correct, now it contains the state "has nil"

Cela étant, vous pouvez vérifier ces variables dans différentes situations:

if let myString = aString? {
     println(myString)
}
else { 
     println("It's nil") // this will print in our case
}

En utilisant le "!" suffixe, vous pouvez également accéder aux valeurs qui les entourent, uniquement si elles existent . (c'est-à-dire qu'il n'est pas nul ):

let aString: String? = "Hello, World!"
// var anotherString: String = aString //error
var anotherString: String = aString!

println(anotherString) //it will print "Hello, World!"

C'est pourquoi vous devez utiliser "?" et "!" et ne pas les utiliser tous par défaut. (ce fut ma plus grande perplexité)

Je suis également d'accord avec la réponse ci-dessus: le type facultatif ne peut pas être utilisé comme booléen .

Teodor Ciuraru
la source
7

Dans l'objectif C, les variables sans valeur étaient égales à «nul» (il était également possible d'utiliser des valeurs «nul» identiques à 0 et fausses), d'où la possibilité d'utiliser des variables dans les instructions conditionnelles (les variables ayant des valeurs sont identiques à «VRAI»). »et ceux sans valeur étaient égaux à« FAUX »).

Swift assure la sécurité du type en fournissant une «valeur facultative». c'est-à-dire qu'il empêche les erreurs formées d'affecter des variables de différents types.

Ainsi, dans Swift, seuls les booléens peuvent être fournis sur des instructions conditionnelles.

var hw = "Hello World"

Ici, même si «hw» est une chaîne, elle ne peut pas être utilisée dans une instruction if comme dans l'objectif C.

//This is an error

if hw

 {..}

Pour cela, il doit être créé comme,

var nhw : String? = "Hello World"

//This is correct

if nhw

 {..}
Gokul
la source
5

La valeur facultative vous permet de montrer l'absence de valeur. Un peu comme NULL en SQL ou NSNull en Objective-C. Je suppose que ce sera une amélioration car vous pouvez l'utiliser même pour les types "primitifs".

// Reimplement the Swift standard library's optional type
enum OptionalValue<T> {
    case None
    case Some(T)
}
var possibleInteger: OptionalValue<Int> = .None
possibleInteger = .Some(100)

Extrait de: Apple Inc. «The Swift Programming Language». iBooks. https://itun.es/gb/jEUH0.l

Maria Zverina
la source
6
nilest juste du sucre syntaxique pour la constante enum OptionalValue<T>.None(où Test le type approprié au contexte dans lequel vous utilisez nil). ?est un raccourci pour OptionalValue<T>.Some(T).
rickster
4

Une option signifie que Swift n'est pas entièrement sûr si la valeur correspond au type: par exemple, Int? signifie que Swift n'est pas entièrement sûr que le nombre soit un Int.

Pour le supprimer, vous pouvez utiliser trois méthodes.

1) Si vous êtes absolument sûr du type, vous pouvez utiliser un point d'exclamation pour forcer le déballage, comme ceci:

// Here is an optional variable:

var age: Int?

// Here is how you would force unwrap it:

var unwrappedAge = age!

Si vous forcez le déballage facultatif et qu'il est égal à zéro, vous pouvez rencontrer cette erreur de plantage:

entrez la description de l'image ici

Ce n'est pas nécessairement sûr, alors voici une méthode qui pourrait empêcher le plantage si vous n'êtes pas certain du type et de la valeur:

Les méthodes 2 et 3 protègent contre ce problème.

2) L'option implicitement déballée

 if let unwrappedAge = age {

 // continue in here

 }

Notez que le type déballé est maintenant Int , plutôt que Int? .

3) La déclaration du gardien

 guard let unwrappedAge = age else { 
   // continue in here
 }

De là, vous pouvez continuer et utiliser la variable non encapsulée. Assurez-vous de ne forcer le déballage (avec un!) Que si vous êtes sûr du type de la variable.

Bonne chance pour votre projet!

GJZ
la source
1

Quand j'ai commencé à apprendre, Swiftil était très difficile de comprendre pourquoi cette option était facultative .

Pensons de cette façon. Considérons une classe Personqui a deux propriétés nameet company.

class Person: NSObject {

    var name : String //Person must have a value so its no marked as optional
    var companyName : String? ///Company is optional as a person can be unemployed that is nil value is possible

    init(name:String,company:String?) {

        self.name = name
        self.companyName = company

    }
}

Permet maintenant de créer quelques objets de Person

var tom:Person = Person.init(name: "Tom", company: "Apple")//posible
var bob:Person = Person.init(name: "Bob", company:nil) // also Possible because company is marked as optional so we can give Nil

Mais on ne peut pas passer Nilàname

var personWithNoName:Person = Person.init(name: nil, company: nil)

Voyons maintenant pourquoi nous utilisons optional?. Considérons une situation où nous voulons ajouter Incaprès le nom de l'entreprise comme le applesera apple Inc. Nous devons ajouter le Incnom de l'entreprise et l'imprimer.

print(tom.companyName+" Inc") ///Error saying optional is not unwrapped.
print(tom.companyName!+" Inc") ///Error Gone..we have forcefully unwrap it which is wrong approach..Will look in Next line
print(bob.companyName!+" Inc") ///Crash!!!because bob has no company and nil can be unwrapped.

Étudions maintenant les raisons pour lesquelles l'option est mise en place.

if let companyString:String = bob.companyName{///Compiler safely unwrap company if not nil.If nil,no unwrap.

    print(companyString+" Inc") //Will never executed and no crash!!!
}

Permet de remplacer bobpartom

if let companyString:String = tom.companyName{///Compiler safely unwrap company if not nil.If nil,no unwrap.

    print(companyString+" Inc") //Will never executed and no crash!!!
}

Et félicitations! nous avons bien géréoptional?

Les points de réalisation sont donc

  1. Nous marquerons une variable comme facultative si elle peut être nil
  2. Si nous voulons utiliser cette variable quelque part dans le compilateur de code, nous vous rappellerons que nous devons vérifier si nous avons correctement traité cette variable si elle contient nil.

Merci ... Joyeux codage

Tunvir Rahman Tusher
la source
0

Permet d'expérimenter avec le code ci-dessous Playground . J'espère effacer l'idée de ce qui est facultatif et la raison de son utilisation.

var sampleString: String? ///Optional, Possible to be nil

sampleString = nil ////perfactly valid as its optional

sampleString = "some value"  //Will hold the value

if let value = sampleString{ /// the sampleString is placed into value with auto force upwraped.

    print(value+value)  ////Sample String merged into Two
}

sampleString = nil // value is nil and the

if let value = sampleString{

    print(value + value)  ///Will Not execute and safe for nil checking
}

//   print(sampleString! + sampleString!)  //this line Will crash as + operator can not add nil
Tunvir Rahman Tusher
la source
0

Depuis https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/OptionalChaining.html :

Le chaînage facultatif est un processus permettant d'interroger et d'appeler des propriétés, des méthodes et des indices sur un facultatif qui peut actuellement être nul. Si l'option facultative contient une valeur, la propriété, la méthode ou l'appel d'indice réussit; si l'option est nil, la propriété, la méthode ou l'appel d'indice renvoie nil. Plusieurs requêtes peuvent être chaînées ensemble et la chaîne entière échoue gracieusement si un lien de la chaîne est nul.

Pour mieux comprendre, lisez le lien ci-dessus.

nizama bunti
la source
0

Bien...

? (Facultatif) indique que votre variable peut contenir une valeur nulle tandis que ! (unwrapper) indique que votre variable doit avoir une mémoire (ou une valeur) lorsqu'elle est utilisée (a essayé d'en obtenir une valeur) au moment de l'exécution.

La principale différence est que le chaînage facultatif échoue correctement lorsque l'option est nulle, tandis que le déballage forcé déclenche une erreur d'exécution lorsque l'option est nulle.

Pour refléter le fait qu'un chaînage facultatif peut être appelé sur une valeur nulle, le résultat d'un appel de chaînage facultatif est toujours une valeur facultative, même si la propriété, la méthode ou l'indice que vous interrogez renvoie une valeur non optionnelle. Vous pouvez utiliser cette valeur de retour facultative pour vérifier si l'appel de chaînage facultatif a réussi (l'option facultative renvoyée contient une valeur) ou n'a pas réussi en raison d'une valeur nulle dans la chaîne (la valeur facultative renvoyée est nulle).

Plus précisément, le résultat d'un appel de chaînage facultatif est du même type que la valeur de retour attendue, mais enveloppé dans un facultatif. Une propriété qui renvoie normalement un Int renvoie un Int? lorsqu'il est accessible via un chaînage facultatif.

var defaultNil : Int?  // declared variable with default nil value
println(defaultNil) >> nil  

var canBeNil : Int? = 4
println(canBeNil) >> optional(4)

canBeNil = nil
println(canBeNil) >> nil

println(canBeNil!) >> // Here nil optional variable is being unwrapped using ! mark (symbol), that will show runtime error. Because a nil optional is being tried to get value using unwrapper

var canNotBeNil : Int! = 4
print(canNotBeNil) >> 4

var cantBeNil : Int = 4
cantBeNil = nil // can't do this as it's not optional and show a compile time error

Voici un didacticiel de base détaillé, par Apple Developer Committee: Chaînage en option

Krunal
la source
-1

Voici une déclaration facultative équivalente dans Swift:

var middleName: String?

Cette déclaration crée une variable nommée middleName de type String. Le point d'interrogation (?) Après le type de variable String indique que la variable middleName peut contenir une valeur qui peut être une chaîne ou nil. Quiconque regarde ce code sait immédiatement que middleName peut être nul. C'est auto-documenté!

Si vous ne spécifiez pas de valeur initiale pour une constante ou variable facultative (comme illustré ci-dessus), la valeur est automatiquement définie sur zéro pour vous. Si vous préférez, vous pouvez définir explicitement la valeur initiale sur nil:

var middleName: String? = nil

pour plus de détails sur le lien facultatif à lire ci-dessous

http://www.iphonelife.com/blog/31369/swift-101-working-swifts-new-optional-values

Devendra Agnihotri
la source
utilisez ceci, var middleName: String! = ""
Gaurav