从dataTask的completionHandler中抛出错误

10

在Swift中,我如何像这样在完成处理程序中引发错误:

    let task = URLSession.shared.dataTask(with: request as URLRequest, completionHandler: {
        (data, response, error) in
        do {
            //something
            completion(result)
        } catch let jsonError {
            throw CustomError.myerror //THIS DOESN'T WORK
        }
    })
    task.resume()

错误提示为

从抛出类型为“(_, _, _) throws -> ()”的函数到非抛出函数类型“(Data?, URLResponse?, Error?) -> Void”的转换无效。


2
可能是无法使带有完成处理程序的函数工作throws的重复问题。 - Enea Dume
1个回答

23

短故事:在 dataTask 的完成处理程序中,您无法throw

您可以在完成处理程序中返回两个值。

...completion: @escaping (ResultType?, Error?)->Void

并返回

completion(result, nil)
completion(nil, CustomError.myerror)

或者更方便的是使用具有关联类型的枚举

enum Result {
    case success(ResultType), failure(Error)
}

...completion: @escaping (Result)->Void

并返回

completion(.success(result))
completion(.failure(CustomError.myerror))
你可以处理结果。
foo() { result in
    switch result {
    case .success(let resultType): // do something with the result
    case .failure(let error): // Handle the error
    }
}

更新:

在 Swift 5 中使用新内置的 Result 类型更加方便,因为 Result 可以捕获抛出表达式的结果。

...completion: @escaping (Result<MyType,Error>)->Void

let task = URLSession.shared.dataTask(with: request as URLRequest, completionHandler: {
    (data, response, error) in

    completion(Result { try something()})
})
task.resume()

更新2:

使用 async/await,完成处理程序已被移除。

do {
    let (data, response) = try await URLSession.shared.data(for: request)
} catch {
     throw CustomError.myerror
}

太棒了,谢谢。我使用了后一种选项。如何检查结果的类型,比如结果是 .success 还是 .failure? - Wayneio
@vadian,我不确定你提供的代码是如何绕过dataTask的类型签名(Data?, URLResponse?, Error?) -> Void的。你能否发布一下如何将此代码-https://pastecode.xyz/view/de5fe2cc并使其返回你提到的枚举? - user2779581

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接