Search code examples
swifttry-catchlabeled-statements

Is it possible to use labeled statements with `throw`?


I have a chain of throwing calls that I need to catch, and then I need to use their result to - maybe - throw something anyway, despite all of them succeeding:

func a() throws {
    do {
        let b = try b()

        if !b.valid {
            throw SomeError()
        }
    } catch {
        throw SomeError()
    }
}

The problem with this code is:

  • I throw inside a do clause
  • This error will also be caught by catch, which I don't want

Now, one could obviously say that I should just let b outside of do:

func a1() {
    let b: B
    do {
        b = try b()
    } catch {
        throw SomeError()
    }
    
    if !b.valid {
        throw SomeError()
    }
}

But I really don't wanna to that because I have a lot of declarations:

func a2() async throws {
    let b1: B
    let b2: B
    let b3: B
    let b4: B
    let b5: B

    // ...
}

Question: is there any way to throw bypassing the catch? Maybe, I could use Swift labeled statements for this?


Solution

  • Labeled statements are for loops. They are not meant for normal functions. For this you could just go through all the errors you have thrown in do statement in catch block. You just need a switch statement. Like this

    enum SomeError: Error {
        case someError
        case anotherError
    }
    
    func a() throws {
        do {
            let b = try b()
    
            if !b.isValid {
                throw SomeError.someError
            }
        } catch {
            switch error {
            case SomeError.someError:
                throw SomeError.someError
            default:
                throw SomeError.anotherError
            }
        }
    }