Francesco Xu
Francesco Xu

Reputation: 83

How to call throw in nested non-throwable closure?

I have this func:

func getOptionalConfigurations(_ configurations: ([String]?, Error?) -> Void) {

    // DO SOMETHING
}

I need to wrap it in another like:

func retrieveConfigurations(_ completion:@escaping (([String]?) throws -> Void)) rethrows {

    getOptionalConfigurations { (configurations: [String]?, error: Error?) in

        do {

            try completion(configurations)

        } catch {

            throw error
        }
    }
}

But I got this error:

Invalid conversion from throwing function of type '([String]?, Error?) throws -> ()' to non-throwing function type '([String]?, Error?) -> Void'

I agree with this error but I would still like to throw the error! I have no chance to change this func: getOptionalConfigurations.

EDIT: the first function is the translation of an ObjC function where at most I can modify the method signature adding something like NS_SWIFT

- (void)getOptionalConfigurations:(void (^)(NSArray <NSString *> * _Nullable configurations, NSError * _Nullable error))completion;

Upvotes: 5

Views: 889

Answers (1)

Anton Kondrashov
Anton Kondrashov

Reputation: 227

If you can't change the function getOptionalConfigurations then you can't throw from inside function because nothing will process the error that you throw.

But if you want to throw the error from the outer function without changing the existing architecture I can propose only a very bad solution:

func retrieveConfigurations(_ completion:@escaping (([String]?) throws -> Void)) throws {
    let d = DispatchGroup()
    var errorToThrow: Error?

    d.enter()
    getOptionalConfigurations { (configurations: [String]?, error: Error?) in
        do {
            try completion(configurations)
            d.leave()
        } catch {
            errorToThrow = error
            d.leave()
        }
    }

    d.wait(timeout: .now() + 10)

    if let error = errorToThrow {
        throw error
    }
}

That's bad because if getOptionalConfigurations is executed async then current thread will have to wait for it's completion. I also added timeout for 10 seconds. You can change that to infinity which will make it even worse or just change the number of seconds.

Upvotes: 1

Related Questions