Recherche…


Introduction

«Une valeur facultative contient une valeur ou contient une valeur nulle pour indiquer qu’une valeur est manquante»

Extrait de: Apple Inc. «Le langage de programmation rapide (Swift 3.1 Edition)». IBooks. https://itun.es/us/k5SW7.l

Les cas d'utilisation optionnels de base incluent: pour une constante (let), utiliser une option dans une boucle (if-let), dérouler en toute sécurité une valeur optionnelle dans une méthode (guard-let), et faire partie des boucles de commutation (casse ), par défaut à une valeur nulle, en utilisant l’opérateur coalesce (??)

Syntaxe

  • var optionalName: optionalType? // déclare un type optionnel, par défaut à nil
  • var optionalName: optionalType? = valeur // déclare une option avec une valeur
  • var optionalName: optionalType! // déclare une option implicitement déballée
  • optionnel! // force à déplier une option

Remarques

Pour plus d'informations sur les options, voir Le langage de programmation Swift .

Types d'option

Les options sont un type enum générique qui agit comme un wrapper. Ce wrapper permet à une variable d'avoir l'un des deux états suivants: la valeur du type défini par l'utilisateur ou nil , qui représente l'absence de valeur.

Cette capacité est particulièrement importante pour Swift car l’un des objectifs de conception du langage est de bien fonctionner avec les frameworks Apple. Beaucoup (la plupart) des frameworks Apple utilisent nil raison de sa facilité d'utilisation et de son importance pour les modèles de programmation et la conception d'API dans Objective-C.

Dans Swift, pour qu'une variable ait une valeur nil , elle doit être facultative. Les options peuvent être créées en ajoutant soit a ! ou un ? au type de variable. Par exemple, pour rendre un Int optionnel, vous pouvez utiliser

var numberOne: Int! = nil
var numberTwo: Int? = nil

? Les options doivent être explicitement déballées et doivent être utilisées si vous n'êtes pas certain si la variable aura une valeur lorsque vous y accéderez. Par exemple, lorsque vous transformez une chaîne en Int , le résultat est un Int? optionnel Int? , car nil sera retourné si la chaîne n'est pas un nombre valide

let str1 = "42"
let num1: Int? = Int(str1) // 42

let str2 = "Hello, World!"
let num2: Int? = Int(str2) // nil

! optionals sont déballés automatiquement et ne doivent être utilisés lorsque vous êtes certain que la variable aura une valeur lorsque vous y accédez. Par exemple, un UIButton! mondial UIButton! variable initialisée dans viewDidLoad()

//myButton will not be accessed until viewDidLoad is called,
//so a ! optional can be used here
var myButton: UIButton!

override func viewDidLoad(){
    self.myButton = UIButton(frame: self.view.frame)
    self.myButton.backgroundColor = UIColor.redColor()
    self.view.addSubview(self.myButton)
}

Déballer une option

Pour accéder à la valeur d'une option, elle doit être déballée.

Vous pouvez déballer conditionnellement une option en utilisant une liaison facultative et forcer un dépliage facultatif en utilisant le ! opérateur.

Déballage conditionnel demande efficacement "Cette variable a-t-elle une valeur?" tandis que le dépliage forcé indique "Cette variable a une valeur!".

Si vous forcez de déplier une variable qui est nil , votre programme lancera un néant trouvé de manière inattendue tout en déroulant une exception facultative et un crash, vous devrez donc examiner attentivement si vous utilisez ! est approprié.

var text: String? = nil
var unwrapped: String = text! //crashes with "unexpectedly found nil while unwrapping an Optional value"

Pour un défilement sécurisé, vous pouvez utiliser une instruction if-let , qui ne lancera pas d'exception ni de blocage si la valeur nil est nil :

var number: Int?
if let unwrappedNumber = number {       // Has `number` been assigned a value?
    print("number: \(unwrappedNumber)") // Will not enter this line
} else {
    print("number was not assigned a value")
}

Ou une déclaration de garde :

var number: Int?
guard let unwrappedNumber = number else {
    return
}
print("number: \(unwrappedNumber)")

Notez que la portée de la variable unwrappedNumber trouve dans l'instruction if-let et à l'extérieur du bloc de guard .

Vous pouvez enchaîner le dépliage de plusieurs options, cela est principalement utile dans les cas où votre code nécessite plus de variables pour s'exécuter correctement:

var firstName:String?
var lastName:String?

if let fn = firstName, let ln = lastName {
    print("\(fn) + \(ln)")//pay attention that the condition will be true only if both optionals are not nil.
}

Notez que toutes les variables doivent être déroulées pour réussir le test, sinon vous n'auriez aucun moyen de déterminer quelles variables ont été déballées et lesquelles ne l'ont pas été.

Vous pouvez enchaîner les instructions conditionnelles en utilisant vos options après leur déballage. Cela signifie pas d'instructions imbriquées if - else!

var firstName:String? = "Bob"
var myBool:Bool? = false

if let fn = firstName, fn == "Bob", let bool = myBool, !bool {
    print("firstName is bob and myBool was false!")
}

Opérateur de coalescence néant

Vous pouvez utiliser l' opérateur de coalescence nil pour déballer une valeur si elle est non-nulle, sinon indiquez une valeur différente:

func fallbackIfNil(str: String?) -> String {
    return str ?? "Fallback String"
}
print(fallbackIfNil("Hi")) // Prints "Hi"
print(fallbackIfNil(nil)) // Prints "Fallback String"

Cet opérateur est capable de court-circuiter , ce qui signifie que si l'opérande gauche est non nul, le bon opérande ne sera pas évalué:

func someExpensiveComputation() -> String { ... }

var foo : String? = "a string"
let str = foo ?? someExpensiveComputation()

Dans cet exemple, comme foo est non-nil, someExpensiveComputation() ne sera pas appelé.

Vous pouvez également enchaîner plusieurs déclarations de coalescence nulle:

var foo : String?
var bar : String?

let baz = foo ?? bar ?? "fallback string"

Dans cet exemple, baz verra attribuer la valeur non foo de foo si elle est non-nulle, sinon la valeur non-emballée de bar lui sera attribuée si elle est non-nulle, sinon la valeur de repli lui sera attribuée.

Chaînage en option

Vous pouvez utiliser le chaînage facultatif pour appeler une méthode , accéder à une propriété ou à un indice en option. Cela se fait en plaçant un ? entre la variable facultative donnée et le membre donné (méthode, propriété ou indice).

struct Foo {
    func doSomething() {
        print("Hello World!")
    }
}

var foo : Foo? = Foo()

foo?.doSomething() // prints "Hello World!" as foo is non-nil

Si foo contient une valeur, doSomething() sera appelé dessus. Si foo est nil , alors rien ne se passera - le code échouera simplement en silence et continuera à s'exécuter.

var foo : Foo? = nil

foo?.doSomething() // will not be called as foo is nil

(Ceci est un comportement similaire à l'envoi de messages à nil dans Objective-C)

La raison pour laquelle le chaînage facultatif est nommé en tant que tel est que «optionality» sera propagé à travers les membres que vous appelez / accédez. Cela signifie que les valeurs de retour des membres utilisés avec un chaînage facultatif seront facultatives, qu'elles soient ou non facultatives.

struct Foo {
    var bar : Int
    func doSomething() { ... }
}

let foo : Foo? = Foo(bar: 5)
print(foo?.bar) // Optional(5)

Ici foo?.bar renvoie un Int? Bien que la bar soit pas facultative, foo lui-même est facultatif.

Comme optionalité se propage, les méthodes de retour Void renverront Void? lorsqu'il est appelé avec chaînage facultatif. Cela peut être utile pour déterminer si la méthode a été appelée ou non (et donc si l'option a une valeur).

let foo : Foo? = Foo()

if foo?.doSomething() != nil {
    print("foo is non-nil, and doSomething() was called")
} else {
    print("foo is nil, therefore doSomething() wasn't called")
}

Ici, nous comparons le Void? retourner la valeur avec nil afin de déterminer si la méthode a été appelée (et donc si foo est non-nil).

Vue d'ensemble - Pourquoi les options?

Souvent, lors de la programmation, il est nécessaire de faire une distinction entre une variable qui a une valeur et une autre qui ne l’a pas. Pour les types de référence, tels que les pointeurs C, une valeur spéciale telle que null peut être utilisée pour indiquer que la variable n'a aucune valeur. Pour les types intrinsèques, comme un entier, cela est plus difficile. Une valeur nominée, telle que -1, peut être utilisée, mais cela dépend de l'interprétation de la valeur. Il élimine également cette valeur "spéciale" de l'utilisation normale.

Pour résoudre ce problème, Swift permet à toute variable d'être déclarée comme facultative. Ceci est indiqué par l'utilisation d'un? ou ! après le type (voir Types de optionnels )

Par exemple,

var possiblyInt: Int?

déclare une variable pouvant ou non contenir une valeur entière.

La valeur spéciale nil indique qu'aucune valeur n'est actuellement affectée à cette variable.

possiblyInt = 5      // PossiblyInt is now 5
possiblyInt = nil    // PossiblyInt is now unassigned

nil peut également être utilisé pour tester une valeur assignée:

if possiblyInt != nil {
    print("possiblyInt has the value \(possiblyInt!)")
}

Notez l'utilisation de ! dans l'instruction print pour dérouler la valeur facultative.

À titre d'exemple d'utilisation commune des options, considérez une fonction qui renvoie un entier à partir d'une chaîne contenant des chiffres; Il est possible que la chaîne contienne des caractères non numériques ou même vide.

Comment une fonction qui retourne un simple Int indiquer un échec? Il ne peut pas le faire en renvoyant une valeur spécifique car cela empêcherait cette valeur d'être analysée à partir de la chaîne.

var someInt
someInt = parseInt("not an integer") // How would this function indicate failure?

Dans Swift, cependant, cette fonction peut simplement renvoyer une option Int. Alors, l'échec est indiqué par la valeur de retour nil .

var someInt?
someInt = parseInt("not an integer")  // This function returns nil if parsing fails
if someInt == nil {
    print("That isn't a valid integer")
}


Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow