Search code examples
iosswiftdropboxdropbox-api

How can I access the associated values of SwiftyDropbox errors?


I’ve been working with SwiftyDropbox and I’m having a curious problem with errors. Specifically, I’m not sure how to manipulate errors in the closure callbacks provided after responses are received so that I can get at their associated values.

For instance, the completion handler for Dropbox.authorizedClient.filesListFolder provides a

CallError<(Files.ListFolderError)>? 

to work with. How would I go about checking if it is a

CallError.HTTPError

, so that I can get the HTTP error code out of it? Right now I’m just sucking that information out of the error’s .description but that doesn’t seem like the right way to do it.

This is what I’ve tried. I suspect I’m failing to understand something with the generics involved.

Xcode Screenshot

client.filesListFolder(path: "", recursive: false).response({ (listFolderResult, listFolderError) -> Void in

    switch listFolderError {
    case let .HTTPError(code, message, requestId):
        print("http error")
    default:
        print("not a http error")
    }

Enum case 'HTTPError' not found in type 'CallError?'


Solution

  • The problem here is that we're trying to switch on an optional. This simpler example highlights the exact same problem:

    enter image description here

    enum Foo {
        case a
        case b
    }
    
    let x: Foo? = nil
    
    switch x {
    case .a:
        print("a")
    case .b:
        print("b")
    }
    

    Enum case 'a' not found in type 'Foo?'

    We can switch over optionals because Optional is itself an Enum, with two cases: None and Some(T).

    So when we're switching over an optional, Swift expects some code like this:

    switch someOptional {
    case .Some(someValue):
        print("do some things")
    case .None:
        print("someOptional was nil")
    }
    

    But that's probably not necessarily particularly useful to use. We have an optional enum, and ultimately, if we dealt with our optional in a switch, we'd just have nested switch statements. Instead, we should deal with our optional in the normal Swift way of dealing with optionals:

    if let error = listFolderError {
        switch error {
        case let .HTTPError(code, message, requestID):
            print("http error")
        default:
            print("some other error")
        }
    } else {
        print("there was no error")
    }