Catch a few types of mistakes?

I am looking for a way to catch several types of errors in catch . I tried fallthrough and comma separated style from switch statement and none of them work. docs don't say anything about catching a few, but pattern 1 . I don’t understand which of the template syntax will work here.

Definitions of errors (sample):

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

Doesn’t compile, is it possible to do something like this?

 do { //... } catch AppErrors.NotFound, AppErrors.AlreadyUsed { makeNewOne() } catch { print("Unhandled error: \(error)") } 
+5
source share
2 answers

If you want to catch all AppErrors , you can use this pattern:

 catch is AppErrors 

If you are looking for a more exact match, it seems like it is quickly becoming ugly.

This will allow us to catch specific cases of AppErrors :

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

There is also this syntax that seems to work:

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

For completeness, I will also add this parameter, which allows us to catch errors of two different types, but this does not allow us to indicate which case is in these types:

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

Finally, based on the fact that everything that we catch will comply with the ErrorType protocol, we can clear the second and third examples that I provided with the ErrorType extension and use this together, where is the where clause in our catch :

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

And just catch it like this:

 catch let error where error.isFooError 
+5
source

You can create a case containing an array of AppErrors :

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

Then for the catch statement:

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

Note, however, that errors is an Array , and order matters when compared to == . An alternative is to use case errors(Set<AppErrors>) , but this requires AppErrors conform to the Hashable protocol.

UPDATE:. Think about it, it's better to use the OptionSet type:

 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

+1
source

Source: https://habr.com/ru/post/1247475/


All Articles