Versuch es! & Versuchen? Was ist der Unterschied und wann wird jeder verwendet?

172

In Swift 2.0 hat Apple eine neue Methode zur Behandlung von Fehlern eingeführt (Do-Try-Catch). Und vor einigen Tagen wurde in Beta 6 ein noch neueres Schlüsselwort eingeführt ( try?). Wusste auch, dass ich verwenden kann try!. Was ist der Unterschied zwischen den drei Schlüsselwörtern und wann sie verwendet werden sollen?

Abdurrahman
quelle

Antworten:

316

Aktualisiert für Swift 5.1

Nehmen Sie die folgende Wurffunktion an:

enum ThrowableError: Error {

    case badError(howBad: Int)
}

func doSomething(everythingIsFine: Bool = false) throws -> String {

  if everythingIsFine {
      return "Everything is ok"
  } else {
      throw ThrowableError.badError(howBad: 4)
  }
}

Versuchen

Sie haben zwei Möglichkeiten, wenn Sie versuchen, eine Funktion aufzurufen, die möglicherweise ausgelöst wird.

Sie können die Verantwortung für die Behandlung von Fehlern übernehmen, indem Sie Ihren Anruf innerhalb eines Do-Catch-Blocks umgeben:

do {
    let result = try doSomething()
}
catch ThrowableError.badError(let howBad) {
    // Here you know about the error
    // Feel free to handle or to re-throw

    // 1. Handle
    print("Bad Error (How Bad Level: \(howBad)")

    // 2. Re-throw
    throw ThrowableError.badError(howBad: howBad)
}

Oder rufen Sie einfach die Funktion auf und geben Sie den Fehler an den nächsten Aufrufer in der Aufrufkette weiter:

func doSomeOtherThing() throws -> Void {    
    // Not within a do-catch block.
    // Any errors will be re-thrown to callers.
    let result = try doSomething()
}

Versuchen!

Was passiert, wenn Sie versuchen, auf eine implizit ausgepackte Option mit einer Null darin zuzugreifen? Ja, stimmt, die App wird abstürzen! Gleiches gilt für try! Grundsätzlich wird die Fehlerkette ignoriert und eine "Do or Die" -Situation deklariert. Wenn die aufgerufene Funktion keine Fehler ausgelöst hat, ist alles in Ordnung. Wenn dies jedoch fehlschlägt und ein Fehler auftritt, stürzt Ihre Anwendung einfach ab .

let result = try! doSomething() // if an error was thrown, CRASH!

Versuchen?

Ein neues Schlüsselwort, das in Xcode 7 Beta 6 eingeführt wurde. Es gibt ein optionales Schlüsselwort zurück, das erfolgreiche Werte auspackt und Fehler durch Rückgabe von nil abfängt.

if let result = try? doSomething() {
    // doSomething succeeded, and result is unwrapped.
} else {
    // Ouch, doSomething() threw an error.
}

Oder wir können Wache benutzen:

guard let result = try? doSomething() else {
    // Ouch, doSomething() threw an error.
}
// doSomething succeeded, and result is unwrapped.

Ein letzter Hinweis hier: Verwenden Sie den try?Hinweis, dass Sie den aufgetretenen Fehler verwerfen, da er in eine Null übersetzt wurde. Verwenden Sie versuchen? Wenn Sie sich mehr auf Erfolge und Misserfolge konzentrieren, nicht darauf, warum Dinge fehlgeschlagen sind.

Verwenden des Koaleszenzoperators?

Sie können den Koaleszenzoperator verwenden? mit versuchen? So geben Sie einen Fehlerwert für den Fall eines Fehlers an:

let result = (try? doSomething()) ?? "Default Value"
print(result) // Default Value
Abdurrahman
quelle
Ihr zweites Codebeispiel ( let result = try doSomething() // Not within a do-catch block) soll aus einer Methode heraus aufgerufen werden, die als deklariert ist throws, oder? Wenn dies doSomething()fehlschlägt, auch die äußere Methode (wiederum)?
Nicolas Miari
Alter Thread und alles außer ich fand das heute (Swift 4, Xcode 9.1) versuchen? Das Ergebnis wird nicht automatisch ausgepackt. Es bleibt nur eine normale Option, die Sie manuell auspacken können. Ich bin mir nicht sicher, ob sich dies seit Swift 2/3 geändert hat, aber es steht in den folgenden Dokumenten: developer.apple.com/library/content/documentation/Swift/… (siehe Konvertieren von Fehlern in optionale Werte ). Tolle Erklärung für den Versuch übrigens.
the_dude_abides
1
in Swift 4 versuchen? Entfernt nicht die Nichtaufrufe von Wurffunktionen, die in 'try'-Ausdrücken in meinem Projekt auftreten.
Aznelite89
7
Sie können auch try?mit verwenden, ??damit Sie einen Standardwert in einer Zeile definieren können:let something:String = (try? whateverIfItThrows()) ?? "Your default value here"
itMaxence