如何在嵌套的非throwable闭包中调用throw?

时间:2018-02-04 09:45:13

标签: swift closures try-catch

我有这个功能:

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

    // DO SOMETHING
}

我需要把它包装在另一个像:

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

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

        do {

            try completion(configurations)

        } catch {

            throw error
        }
    }
}

但我收到了这个错误:

  

投掷类型'的函数转换无效([String]?,错误?)   投掷 - > ()'到非投掷函数类型'([String]?,错误?) - >   无效“

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

修改 第一个函数是ObjC函数的转换,我最多可以修改方法签名,添加类似 NS_SWIFT

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

1 个答案:

答案 0 :(得分: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
    }
}

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