2016-01-06 6 views
14

Ich habe in diesem blöd Verhalten in Swift, wo Force-Unwrapping eine optionale nicht propagiert.Schnelle Force-Unwrapping Ausnahme nicht propagiert

Aus der Dokumentation:

zu verwenden Versuch! Der Zugriff auf einen nicht vorhandenen optionalen Wert löst einen Laufzeitfehler aus. Stellen Sie immer sicher, dass ein optionales Element vor der Verwendung einen Nicht-Nullwert enthält! um seinen Wert zu erzwingen.

zu reproduzieren:

func foo(bar:String?) throws{ 
    print(bar!); 
} 

Und

try foo(nil); 

Dies gilt nicht logisch oder konsistent erscheinen mir und ich zu diesem Thema alle Unterlagen nicht finden können.

Ist das von Entwurf?

+2

Ich bin mir nicht sicher, dass das Werfen eines Fehlers mit 'throw' (was dazu führt, dass Fehler innerhalb einer solchen Funktion propagiert werden) dasselbe ist, was passiert, wenn man ein' nil' erzwingt. Ich glaube, ich habe irgendwo gelesen, dass es als 'assert()' implementiert ist. –

+0

Das würde es erklären, aber das ist schrecklich. Vielleicht gibt es ein Argument dafür, aber in einer Sprache, die Ausnahmen unterstützt, scheint es nur inkonsistent zu sein. – Greg

+7

@Greg: Nicolas hat Recht. Beachten Sie, dass try/catch-Handles Swift * -Fehler * (Werte, die mit 'ErrorType' übereinstimmen) ausgelöst werden. Das ist * völlig unabhängig von Laufzeitfehlern oder Ausnahmen. (Die Dokumentation erwähnt nicht einmal das Wort "Ausnahme" in Verbindung mit throw/try/catch, nur "Fehlerbehandlung".) –

Antwort

10

Vom documentation:

Fehler

Fehlerbehandlung Handhabung ist der Prozess zu reagieren und von Fehlerbedingungen in Ihrem Programm zu erholen. Swift bietet erstklassige Unterstützung für das Werfen, Abfangen, Weiterleiten und Bearbeiten behebbarer Fehler zur Laufzeit.

...

Darstellen und Wurffehler

In Swift werden Fehler durch Werte von Typen dargestellt, das ErrorType Protokoll entsprechen. Dieses leere Protokoll zeigt an, dass ein Typ für die Fehlerbehandlung verwendet werden kann.

:

So (Hinweis ErrorType wurde Error in Swift 3 umbenannt) mit try/catch Sie behandeln Swift Fehler (Werte von Typen, die mit dem ErrorType Protokoll entsprechen), die throw n sind. Dies steht in keinem Zusammenhang mit Laufzeitfehlern und Laufzeitausnahmen (und auch nicht verwandt mit NSException aus der Foundation-Bibliothek).

Beachten Sie, dass die Swift-Dokumentation zur Fehlerbehandlung verwenden nicht einmal die Wort "Ausnahme", mit der einzigen Ausnahme in (Hervorhebung von mir) in (!):

HINWEIS

Fehlerbehandlung in Swift ähnelt Ausnahmebehandlung in anderen Sprachen, mit der Verwendung der Schlüsselwörter versuchen, fangen und werfen.Im Gegensatz zu Ausnahmebehandlung in vielen Sprachen-einschließlich Objective-C-Fehler Handhabung in Swift umfasst nicht Abwickeln der Aufruf-Stack, ein Prozess , die rechenintensiv sein kann. Daher sind die Leistungsmerkmale einer throw-Anweisung mit denen einer return-Anweisung vergleichbar.

Die Auswickeln von optionals die nil nicht throw a Swift Fehler sind (die vermehrt werden könnten) und gehandhabt werden können, nicht mit try.

Sie haben die bekannten Techniken wie optionale Bindung, optional Verkettung zu verwenden, die Überprüfung gegen nil usw.

+0

Ich habe noch nie versucht zu versuchen, die Entpackung zu fangen, ich spreche nur über sie propagieren. Aber Sie antworten das ganz gut. Ein Anwendungsfall, in den ich lief, ist SwiftyJSON und Parsing Json. Ich habe eine Entität, die eine Kind-Entität enthält, die einfach das nicht existierende Feld in der JSON-Antwort werfen (propagieren) würde. Ich benutze jetzt optionale Initialisierer, um die gleiche Sache zu erreichen, aber jetzt gibt es noch 3 Zeilen Code: P – Greg

+0

@Greg: Nun, jeder geworfene Fehler muss irgendwo eingefangen werden. Aber ich habe den Wortlaut so geändert, dass er besser zu Ihrer Frage passt. –

5

diese ‚selbsterklärend‘ Beispiel kann Ihnen helfen, den Unterschied zwischen Auslösen einer Laufzeitausnahme und werfen, um zu sehen ein Fehler E, der dem ErrorType-Protokoll entspricht.

struct E: ErrorType{} 
func foo(bar:String?) throws { 
    if let error = bar where error == "error" { 
      throw E() 
    } 
    print(bar, "is valid parameter, but don't try to access bar.characters, it crash your code! (if bar == nil)") 
    // here is everything OK 
    let bar = bar! 
    // but here it crash!! 
    _ = bar.characters 
} 

do { 
    try foo("error") 
    // next line is not accessible here ... 
    try foo(nil) 
} catch { 
    print("\"error\" as parameter of foo() throws an ERROR!") 
} 
do { 
    try foo(nil) // fatal error: unexpectedly found nil while unwrapping an Optional value 
} catch { 

} 

druckt

"error" as parameter of foo() throws an ERROR! 
nil is valid parameter, but don't try to access bar.characters, it crash your code! (if bar == nil) 
fatal error: unexpectedly found nil while unwrapping an Optional value 

Erhöhung eine Laufzeitausnahme in Ihrem Code fataler Fehler ist.

Verwandte Themen