2016-04-19 7 views
4

Ich suche nach einer Möglichkeit, mehrere Arten von Fehlern in einer catch zu fangen. Ich habe versucht fallthrough und das Komma getrennte Stil von einer switch-Anweisung und keiner funktioniert. Die docs sagen nichts über das Fangen mehrerer aber pattern 1. Mir ist nicht klar, welche der Pattern-Syntaxen hier funktionieren würde.Fangen mehrere errorTypes?

Fehlerdefinitionen (Beispiel):

enum AppErrors { 
    case NotFound(objectType: String, id: Int) 
    case AlreadyUsed 
} 

Works:

do { 
    //... 
} catch AppErrors.NotFound { 
    makeNewOne() 
} catch AppErrors.AlreadyUsed { 
    makeNewOne() 
} catch { 
    print("Unhandled error: \(error)") 
} 

nicht kompilieren lässt, ist es möglich, so etwas zu tun?

do { 
    //... 
} catch AppErrors.NotFound, AppErrors.AlreadyUsed { 
    makeNewOne() 
} catch { 
    print("Unhandled error: \(error)") 
} 

Antwort

5

Wenn Sie alle AppErrors fangen wollen, können Sie dieses Muster verwenden können:

catch is AppErrors 

Wenn Sie spezifischere passende suchen, scheint es schnell hässlich.

Dies lässt uns konkrete Fälle von AppErrors fangen:

catch let error as AppErrors where error == .NotFound || error == .AlreadyUsed 

Es gibt auch diese Syntax, die zu funktionieren scheint:

catch let error as AppErrors where [.NotFound, .AlreadyUsed].contains(error) 

Der Vollständigkeit halber werde ich auch diese Option hinzufügen, die ermöglicht es uns, Fehler von zwei verschiedenen Typen zu erkennen, aber es erlaubt uns nicht, den Fall innerhalb dieser Typen zu spezifizieren:

catch let error where error is AppErrors || error is NSError 

Schließlich basierte auf der Tatsache, dass etwas wir das ErrorType Protokoll entsprechen fangen, können wir die zweiten & dritten Beispiele aufzuräumen ich mit einer ErrorType Verlängerung und verwenden, die in Verbindung, wo eine where Klausel unsere catch:

extension ErrorType { 
    var isFooError: Bool { 
     guard let err = self as? AppErrors else { return false } 
     return err == .NotFound || err == .AlreadyUsed 
    } 
} 

Und es einfach so fangen:

catch let error where error.isFooError 
+0

Wenn ich versuche, 'fangen lassen Fehler als AppErrors wo Fehler == .NotFound ', Bekomme ich die Fehlermeldung' binary operator == kann nicht auf zwei AppErrors-Operanden angewendet werden'. Ich denke, das liegt daran, dass diese errorTypes verknüpfte Werte haben. Gibt es einen Weg dahin? – SimplGy

+0

Ich denke, die'ErrorType'-Erweiterung am Ende der Antwort kann wahrscheinlich dafür arbeiten. – nhgrif

+0

Da es eine '== 'Implementierung zum Vergleich verwendet, funktioniert es auch nicht. Im Moment denke ich, dass nur eine Switch-Implementierung mehrere zugehörige errorTypes zusammenfassen kann. – SimplGy

1

Sie können einen Fall erstellen, die eine AppErrors Array enthält:

indirect enum AppErrors: Error { 
    case NotFound 
    case AlreadyUsed 
    case errors([AppErrors]) 
} 

Dann wird für die catch-Anweisung:

catch AppErrors.errors(let errors) where errors == [.NotFound, .AlreadyUsed] 

Anmerkung Sie jedoch, dass errors ein Array ist und die Ordnung zählt wenn Vergleich mit ==. Eine Alternative ist die Verwendung von case errors(Set<AppErrors>), aber das würde AppErrors erfordern, um dem Protokoll Hashable zu entsprechen.

UPDATE: Kommen Sie, daran zu denken, ist es besser, einen OptionSet Typ zu verwenden:

public struct InvalidInput: OptionSet, Error { 
    public var rawValue: Int 

    public init(rawValue: Int) { 
     self.rawValue = rawValue 
    } 

    public static let noAccount = InvalidInput(rawValue: 1 << 0) 
    public static let noKey  = InvalidInput(rawValue: 1 << 1) 
    public static let invalidKey = InvalidInput(rawValue: 1 << 2) 
} 

func validateInput() throws -> Void { 
    var invalid: InvalidInput = [] 

    invalid.insert(.noKey) 
    invalid.insert(.noAccount) 

    if !invalid.isEmpty { 
     throw invalid 
    } 
} 

do { 
    try validateInput() 
} catch [InvalidInput.noAccount, InvalidInput.noKey] as InvalidInput { 
    print("Account and key are both required.") 
} 

-Link: http://www.chrisamanse.xyz/2016/12/03/catching-multiple-errors-in-swift