Erklärung für Error-Handling gesucht

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • Erklärung für Error-Handling gesucht

    Hallo zusammen!

    Die Hölle friert zu und ich fange an, in kleinen Schritten Funktionen meines Alt-Projektes in Swift zu realisieren. Es fühlt sich noch komisch an und häufiger bin ich unsicher, ob der von mir geschriebene Code "korrekt" ist: Er macht, was er soll - fühlt sich aber merkwürdig an.

    So auch hier in einem Fall der Fehlerbehandlung. Zunächst der relevante Code (eingekürzt):

    Quellcode

    1. openPanel.beginSheetModal(for:self.window!) { (response) in
    2. if response == .OK {
    3. if let imageURL = openPanel.url {
    4. let fileManager = FileManager.default
    5. if var targetURL = fileManager.urls(for: .applicationSupportDirectory, in: .userDomainMask).first {
    6. targetURL.appendPathComponent(UUID().uuidString)
    7. targetURL.appendPathExtension(imageURL.pathExtension)
    8. try fileManager.moveItem(at: imageURL, to: targetURL)
    9. } }
    10. }
    11. }
    12. openPanel.close()
    13. }
    Alles anzeigen

    Ich präsentiere also ein "Open"-Panel und anschliessend soll (unter anderem) eine Datei verschoben werden. Hierbei interessiert mich ganz bewusst nicht, ob dieser Vorgang erfolgreich war. Ich habe daher dem FileManager.moveItem ein try ohne catch vorangestellt. Allerdings meckert Xcode dann bei der beginSheetModal-Funktion:

    Invalid conversion from throwing function of type '(NSApplication.ModalResponse) throws -> Void' to non-throwing function type '(NSApplication.ModalResponse) -> Void'
    Ich vermute, weil moveItem einen Fehler werfen könnte, die Deklaration von beginSheetModal dies aber nicht vorsieht. Das Ganze funktioniert, wenn ich per try? ein Optional try verwende. Dann - so verstehe ich es - wird im Fehlerfall "nur" nil zurückgegeben, keine Exception ausgelöst.

    Ist mein Verständnis korrekt oder was stimmt nicht? Wie würdet Ihr den Fall lösen? Gibt es sonst Dinge im obigen Code, die "so gar nicht gehen"? Ich bin für jede Korrektur dankbar :)

    Mattes

    P.S.: Ist es normal, dass man in Swift durch das viele Unwrapping von Optionals massenhaft if-Klauseln schachtelt - oder wie vermeidet Ihr das?
    Diese Seite bleibt aus technischen Gründen unbedruckt.
  • Wenn der Completion-Block mit `rethrows` gekennzeichnet ist, wird der Fehler aus dem Block nach außen weitergegeben und die Behandlung muss dann im Aufrufer von `beginModal()` erfolgen. Wenn du den Fehler nicht verarbeiten willst, kannst du ihn auch durch ein `try?` direkt für `moveItem()` ignorieren.

    Wenn du `fileManager` am Anfang des Blocks initialisierst, dann kannst du die drei Ifs zu einem Zusammenfassen. Etwas ungewöhnlich dabei ist allerdings, dass die Variablenzuweisungen in der Bedingung durch Kommata anstatt `&&` getrennt werden.
    „Meine Komplikation hatte eine Komplikation.“
  • Die Verwendung von Kommata anstelle von '&&' bei einem if gefällt mir sehr gut und ich nutze dies dann auch. :)

    Bei mir würde der o.a. Code dann in etwa so aussehen:

    Quellcode

    1. openPanel.beginSheetModal(for:self.window!) { (response) in
    2. let fileManager = FileManager.default
    3. if response == .OK, let imageURL = openPanel.url, var targetURL = fileManager.urls(for: .applicationSupportDirectory, in: .userDomainMask).first {
    4. targetURL.appendPathComponent(UUID().uuidString)
    5. targetURL.appendPathExtension(imageURL.pathExtension)
    6. try fileManager.moveItem(at: imageURL, to: targetURL)
    7. }
    8. openPanel.close()
    9. }

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von MCDan ()

  • Ich bevorzuge immer das Return-Early Pattern. Also das If Let ist zwar schön aber:
    1. Muss man ja meist, wenn die Bedingung nicht eintrifft ein Error-Handling machen
    2. Kommt man dann unter Umständen zum if im if was hässlich ist.


    Ich würde das wie folgt schreiben:

    Quellcode

    1. guard response == .OK,
    2. let imageURL = openPanel.url,
    3. let targetURL = fileManager.urls(for: .applicationSupportDirectory, in: .userDomainMask).first else {
    4. //TODO Error Handling
    5. return
    6. }
    7. targetURL.appendPathComponent(UUID().uuidString)
    8. targetURL.appendPathExtension(imageURL.pathExtension)
    9. try fileManager.moveItem(at: imageURL, to: targetURL)