Suche…


Einführung

„Ein optionaler Wert enthält entweder einen Wert oder enthält Null, um anzuzeigen, dass ein Wert fehlt.“

Auszug aus: Apple Inc. „Die Programmiersprache Swift (Swift 3.1 Edition).“ IBooks. https://itun.es/us/k5SW7.l

Grundlegende optionale Anwendungsfälle umfassen: für eine Konstante (let) die Verwendung einer optionalen Option innerhalb einer Schleife (if-let), das sichere Entpacken eines optionalen Werts innerhalb einer Methode (guard-let) und als Teil von switch-Schleifen (case-let) ), Standardwert mit null, wenn der Koaleszenzoperator verwendet wird (??)

Syntax

  • var optionalName: optionalTyp? // einen optionalen Typ angeben, der Standardwert ist null
  • var optionalName: optionalTyp? = value // deklarieren Sie optional einen Wert
  • var optionalName: optionalType! // ein implizit nicht verpacktes optionales deklarieren
  • wahlweise! // erzwinge das Auspacken eines optionalen Elements

Bemerkungen

Weitere Informationen zu Optionen finden Sie unter Die Swift-Programmiersprache .

Arten von Optionals

Optionals sind ein generischer Aufzählungstyp, der als Wrapper fungiert. Mit diesem Wrapper kann eine Variable zwei Zustände annehmen: den Wert des benutzerdefinierten Typs oder nil , der das Fehlen eines Werts darstellt.

Diese Fähigkeit ist besonders wichtig in Swift, da eines der angegebenen Designziele der Sprache darin besteht, gut mit Apples Frameworks zusammenzuarbeiten. Viele (die meisten) Apple-Frameworks verwenden nil da sie einfach zu verwenden sind und für Programmiermuster und API-Design in Objective-C von Bedeutung sind.

In Swift muss eine Variable optional sein, damit eine Variable einen nil hat. Optionale können erstellt werden, indem Sie entweder ein ! oder ein ? auf den Variablentyp. Um beispielsweise ein Int optional zu machen, können Sie verwenden

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

? Optionals müssen explizit nicht umschlossen sein und sollten verwendet werden, wenn Sie nicht sicher sind, ob die Variable beim Zugriff einen Wert haben soll. Wenn Sie beispielsweise eine Zeichenfolge in eine Int , ist das Ergebnis eine optionale Int? , weil nil zurückgegeben wird, wenn der String keine gültige Zahl ist

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

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

! Optionals werden automatisch entpackt und sollten nur verwendet werden, wenn Sie sicher sind , dass die Variable einen Wert hat, wenn Sie darauf zugreifen. Zum Beispiel ein globaler UIButton! Variable, die in viewDidLoad() initialisiert wird

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

Auspacken einer Option

Um auf den Wert eines Optional zugreifen zu können, muss es umwickelt sein.

Sie können ein optionales Element mit der optionalen Bindung bedingt auspacken und ein optionales Packen mit der Option ! Operator.

Bedingtes Entpacken erfordert die Frage "Hat diese Variable einen Wert?" Während erzwungenes Entpacken sagt: "Diese Variable hat einen Wert!".

Wenn Sie eine Variable erzwingen auszupacken , das ist nil , wird Ihr Programm eine unerwartet gefunden werfen Null , während eine optionale Ausnahme und Absturz auszupacken, so müssen Sie sorgfältig prüfen , ob mit ! Ist angemessen.

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

Für ein sicheres Entpacken können Sie eine if-let Anweisung verwenden, die keine Ausnahme auslöst oder abstürzt, wenn der umschlossene Wert 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")
}

Oder eine Wachaussage :

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

Beachten Sie, dass der Gültigkeitsbereich der unwrappedNumber Variablen innerhalb der if-let Anweisung und außerhalb des guard Blocks liegt.

Sie können das Auspacken vieler Optionals verketten. Dies ist vor allem in Fällen nützlich, in denen für Ihren Code mehr als die korrekte Ausführung der Variablen erforderlich ist:

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

Beachten Sie, dass alle Variablen entpackt werden müssen, um den Test erfolgreich zu bestehen. Andernfalls können Sie nicht feststellen, welche Variablen entpackt wurden und welche nicht.

Sie können bedingte Anweisungen mithilfe Ihrer Optionals unmittelbar nach dem Auspacken verketten. Dies bedeutet keine verschachtelten if-else-Anweisungen!

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

Kein Koaleszenz-Operator

Sie können die Verwendung nil Koaleszierstruktur Operator Wert auszupacken , wenn es nicht Null ist, andernfalls einen anderen Wert zur Verfügung stellen:

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

Dieser Operator kann einen Kurzschluss ausführen , dh wenn der linke Operand nicht Null ist, wird der rechte Operand nicht ausgewertet:

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

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

In diesem Beispiel wird someExpensiveComputation() nicht aufgerufen, da foo nicht null ist.

Sie können auch mehrere null koaleszierende Anweisungen miteinander verketten:

var foo : String?
var bar : String?

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

In diesem Beispiel wird baz der unverpackte Wert von foo zugewiesen, wenn es nicht null ist. Andernfalls wird ihm der unverpackte Wert von bar zugewiesen, wenn es nicht null ist.

Optionale Verkettung

Sie können die optionale Verkettung verwenden, um eine Methode aufzurufen, auf eine Eigenschaft zuzugreifen oder auf ein optionales Abonnement zuzugreifen. Dies wird durch Platzieren eines ? zwischen der angegebenen optionalen Variable und dem angegebenen Member (Methode, Eigenschaft oder Index).

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

var foo : Foo? = Foo()

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

Wenn foo einen Wert enthält, wird doSomething() für ihn aufgerufen. Wenn foo nil , wird nichts Schlimmes passieren - der Code schlägt einfach im Hintergrund fehl und läuft weiter.

var foo : Foo? = nil

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

(Dies ist ein ähnliches Verhalten wie das Senden von Nachrichten an nil in Objective-C.)

Der Grund für die Benennung der optionalen Verkettung ist, dass 'Optionalität' durch die von Ihnen angerufenen Mitglieder propagiert wird. Dies bedeutet, dass die Rückgabewerte aller Elemente, die für die optionale Verkettung verwendet werden, optional sind, unabhängig davon, ob sie als optional eingegeben werden oder nicht.

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

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

Hier foo?.bar ein Int? obwohl bar nicht optional ist, da foo selbst optional ist.

Wenn Optionalität propagiert wird, geben Methoden, die Void zurückgeben, Void? wenn mit optionaler Verkettung aufgerufen. Dies kann nützlich sein, um festzustellen, ob die Methode aufgerufen wurde oder nicht (und daher, ob die Option einen Wert hat).

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

Hier vergleichen wir die Void? Rückgabewert mit nil um zu bestimmen, ob die Methode aufgerufen wurde (und daher, ob foo nicht null ist).

Übersicht - Warum Optionals?

Bei der Programmierung ist es oft notwendig, zwischen einer Variablen, die einen Wert hat, und einer Variablen, die keinen Wert hat, zu unterscheiden. Für Referenztypen wie C-Zeiger kann ein spezieller Wert wie null verwendet werden, um anzuzeigen, dass die Variable keinen Wert hat. Bei intrinsischen Typen wie einer Ganzzahl ist dies schwieriger. Ein nominierter Wert wie -1 kann verwendet werden, dies hängt jedoch von der Interpretation des Werts ab. Es beseitigt auch diesen "speziellen" Wert aus dem normalen Gebrauch.

Um dies zu beheben, ermöglicht Swift, dass jede Variable als optional deklariert wird. Dies wird durch die Verwendung eines? oder ! hinter dem Typ (Siehe Optionsarten )

Zum Beispiel,

var possiblyInt: Int?

deklariert eine Variable, die einen ganzzahligen Wert enthalten kann oder nicht.

Der Sonderwert nil gibt an, dass dieser Variablen derzeit kein Wert zugewiesen ist.

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

nil können Sie auch einen zugewiesenen Wert testen:

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

Beachten Sie die Verwendung von ! in der Druckanweisung, um den optionalen Wert auszupacken .

Als Beispiel für eine häufige Verwendung von Optionals betrachten Sie eine Funktion, die eine Ganzzahl aus einer Zeichenfolge zurückgibt, die Ziffern enthält. Es ist möglich, dass die Zeichenfolge nicht-stellige Zeichen enthält oder sogar leer ist.

Wie kann eine Funktion, die ein einfaches Int zurückgibt, einen Fehler anzeigen? Es kann dies nicht tun, indem ein bestimmter Wert zurückgegeben wird, da dies verhindern würde, dass dieser Wert aus der Zeichenfolge analysiert wird.

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

In Swift kann diese Funktion jedoch einfach einen optionalen Int zurückgeben. Der Fehler wird dann durch den Rückgabewert von nil angezeigt.

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
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow