如何在嵌套的不可抛出闭包中调用 throw ?

Fra*_* Xu 5 closures try-catch swift

我有这个功能:

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

    // DO SOMETHING
}
Run Code Online (Sandbox Code Playgroud)

我需要将它包装在另一个中,例如:

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

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

        do {

            try completion(configurations)

        } catch {

            throw error
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

但我收到了这个错误:

从类型“([String]?, Error?) throws -> ()”的抛出函数到非抛出函数类型“([String]?, Error?) -> Void”的转换无效

我同意这个错误,但我仍然想抛出这个错误!我没有机会更改功能:getOptionalConfigurations

编辑: 第一个函数是 ObjC 函数的翻译,我最多可以修改方法签名,添加类似NS_SWIFT的内容

- (void)getOptionalConfigurations:(void (^)(NSArray <NSString *> * _Nullable configurations, NSError * _Nullable error))completion;
Run Code Online (Sandbox Code Playgroud)

Ant*_*hov 0

如果您无法更改函数 getOptionalConfigurations,那么您就无法从函数内部抛出异常,因为没有任何东西会处理您抛出的错误。

但是如果你想从外部函数抛出错误而不改变现有的架构,我只能提出一个非常糟糕的解决方案:

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
    }
}
Run Code Online (Sandbox Code Playgroud)

这很糟糕,因为如果getOptionalConfigurations异步执行,那么当前线程将不得不等待它完成。我还添加了 10 秒的超时。您可以将其更改为无穷大,这会使情况变得更糟,或者只是更改秒数。