Ricerca…


introduzione

"Un valore opzionale contiene un valore o contiene nil per indicare che manca un valore"

Estratto da: Apple Inc. "The Swift Programming Language (Swift 3.1 Edition)." IBooks. https://itun.es/us/k5SW7.l

I casi d'uso facoltativi di base includono: per una costante (let), l'uso di un facoltativo all'interno di un ciclo (if-let), lo srotolamento sicuro di un valore facoltativo all'interno di un metodo (guard-let) e come parte di cicli di commutazione (caso-let ), per impostazione predefinita su un valore se nil, utilizzando l'operatore di coalesce (??)

Sintassi

  • var optionalName: optionalType? // dichiara un tipo facoltativo, il valore predefinito è nullo
  • var optionalName: optionalType? = valore // dichiara un opzionale con un valore
  • var optionalName: optionalType! // dichiara un facoltativo facoltativo da scartare
  • opzionale! // forza scartare un opzionale

Osservazioni

Per ulteriori informazioni sugli optionals, vedere The Swift Programming Language .

Tipi di Optionals

Gli optionals sono un tipo enum generico che funge da wrapper. Questo wrapper consente a una variabile di avere uno o due stati: il valore del tipo definito dall'utente o nil , che rappresenta l'assenza di un valore.

Questa capacità è particolarmente importante in Swift perché uno degli obiettivi di design dichiarati della lingua è quello di funzionare bene con i framework di Apple. Molti (molti) framework di Apple utilizzano nil causa della sua facilità d'uso e significato per i pattern di programmazione e il design delle API all'interno di Objective-C.

In Swift, affinché una variabile abbia un valore nil , deve essere facoltativa. Gli optionals possono essere creati aggiungendo a ! o un ? al tipo di variabile. Ad esempio, per rendere un Int opzionale, è possibile utilizzare

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

? le opzioni devono essere esplicitamente scartate e dovrebbero essere utilizzate se non si è certi che la variabile abbia o meno un valore quando si accede ad essa. Ad esempio, quando si trasforma una stringa in un Int , il risultato è un Int? opzionale Int? , perché nil verrà restituito se la stringa non è un numero valido

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

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

! le opzioni vengono scartate automaticamente e dovrebbero essere utilizzate solo quando si è certi che la variabile avrà un valore quando ci si accede. Ad esempio, un UIButton! globale UIButton! variabile inizializzata in 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)
}

Scartare un facoltativo

Per accedere al valore di un Opzionale, deve essere scartato.

È possibile scartare condizionatamente un Opzionale usando l'associazione opzionale e forzare scartare un Opzionale usando il ! operatore.

Lo srotolamento condizionato richiede in modo efficace "Questa variabile ha un valore?" mentre force unwrapping dice "Questa variabile ha un valore!".

Se imposti di scartare una variabile nil , il tuo programma genererà un risultato inaspettato nullo mentre scarterai un'eccezione opzionale e si bloccherà, quindi devi valutare attentamente se usi ! è appropriato.

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

Per lo srotolamento sicuro, è possibile utilizzare un'istruzione if-let , che non genererà un'eccezione o un arresto anomalo se il valore spostato è 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")
}

O una dichiarazione di guardia :

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

Si noti che l'ambito della variabile unwrappedNumber trova all'interno unwrappedNumber if-let e all'esterno del blocco di guard .

Puoi concatenare la scartocciatura di molti optionals, questo è utile soprattutto nel caso in cui il tuo codice richieda più di una variabile per funzionare correttamente:

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.
}

Si noti che tutte le variabili devono essere scartate per passare correttamente il test, altrimenti non si avrebbe modo di determinare quali variabili sono state scartate e quali no.

Puoi concatenare le dichiarazioni condizionali usando i tuoi optionals immediatamente dopo averli scartati. Questo significa che non ci sono nested if - else statements!

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!")
}

Nil Coalescing Operator

Puoi utilizzare l' operatore a coalescenza nil per scartare un valore se non è zero, altrimenti fornire un valore diverso:

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

Questo operatore è in grado di cortocircuitare , nel senso che se l'operando di sinistra non è zero, l'operando di destra non verrà valutato:

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

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

In questo esempio, poichè foo è non-nil, someExpensiveComputation() non saranno chiamati.

Puoi anche concatenare più istruzioni coalescenti nil:

var foo : String?
var bar : String?

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

In questo esempio baz verrà assegnato al valore unwrapped di foo se non è zero, altrimenti verrà assegnato il valore unwrapped della bar se non è zero, altrimenti verrà assegnato il valore di fallback.

Concatenamento opzionale

È possibile utilizzare il concatenamento opzionale per chiamare un metodo , accedere a una proprietà o pedice facoltativo. Questo viene fatto posizionando un ? tra la variabile opzionale data e il membro dato (metodo, proprietà o pedice).

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

var foo : Foo? = Foo()

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

Se foo contiene un valore, doSomething() verrà chiamato su di esso. Se foo è nil , allora non accadrà nulla di male: il codice fallirà semplicemente in silenzio e continuerà ad essere eseguito.

var foo : Foo? = nil

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

(Questo è un comportamento simile all'invio di messaggi a nil in Objective-C)

La ragione per cui il concatenamento facoltativo è chiamato così è perché "l'opzionalità" sarà propagata attraverso i membri che chiami / acceda. Ciò significa che i valori di ritorno di tutti i membri utilizzati con il concatenamento facoltativo saranno facoltativi, indipendentemente dal fatto che siano stati digitati come facoltativi o meno.

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

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

Qui foo?.bar sta restituendo un Int? anche se la bar non è opzionale, poichè foo stesso è facoltativo.

Mentre l'opzionalità viene propagata, i metodi che restituiscono Void restituiranno Void? quando viene chiamato con concatenamento opzionale. Questo può essere utile per determinare se il metodo è stato chiamato o meno (e quindi se l'opzione ha un valore).

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")
}

Qui stiamo confrontando il Void? restituire il valore con nil per determinare se il metodo è stato chiamato (e quindi se foo è non-zero).

Panoramica - Perché Optionals?

Spesso durante la programmazione è necessario fare una distinzione tra una variabile che ha un valore e una che non lo fa. Per i tipi di riferimento, come C Pointers, è possibile utilizzare un valore speciale come null per indicare che la variabile non ha alcun valore. Per tipi intrinseci, come un numero intero, è più difficile. È possibile utilizzare un valore nominale, ad esempio -1, ma ciò dipende dall'interpretazione del valore. Elimina anche quel valore "speciale" dal normale utilizzo.

Per risolvere questo problema, Swift consente a qualsiasi variabile di essere dichiarata come facoltativa. Questo è indicato dall'uso di un? o ! dopo il tipo (Vedi Tipi di optionals )

Per esempio,

var possiblyInt: Int?

dichiara una variabile che può o non può contenere un valore intero.

Il valore speciale nil indica che al momento non è assegnato alcun valore a questa variabile.

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

nil può anche essere usato per testare un valore assegnato:

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

Nota l'uso di ! nell'istruzione print per scartare il valore opzionale.

Come esempio di un uso comune di optionals, si consideri una funzione che restituisce un intero da una stringa contenente cifre; È possibile che la stringa contenga caratteri non numerici o addirittura vuota.

In che modo una funzione che restituisce un semplice Int indica un errore? Non può farlo restituendo un valore specifico in quanto ciò impedirebbe che il valore venga analizzato dalla stringa.

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

In Swift, tuttavia, quella funzione può semplicemente restituire un Int opzionale . Quindi il fallimento è indicato dal valore di ritorno di 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
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow