在Swift 2中处理异步关闭错误的最佳方法? [英] Best way to handle errors from async closures in Swift 2?
问题描述
我正在使用大量异步网络请求(顺便说一下,iOS中的任何网络请求都需要异步),并且我正在寻找方法来更好地处理不支持throws
的Apple dataTaskWithRequest
中的错误.
I'm using a lot of async network request (btw any network request in iOS need to by async) and I'm finding way to better handle errors from Apple's dataTaskWithRequest
which not supports throws
.
我有这样的代码:
func sendRequest(someData: MyCustomClass?, completion: (response: NSData?) -> ()) {
let request = NSURLRequest(URL: NSURL(string: "http://google.com")!)
if someData == nil {
// throw my custom error
}
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
data, response, error in
// here I want to handle Apple's error
}
task.resume()
}
我需要解析可能的自定义错误并处理来自dataTaskWithRequest
的可能的连接错误. Swift 2引入了throws
,但是您不能从Apple的关闭中退出,因为它们不支持抛出并且运行异步.
I need to parse my possible custom errors and handle possible connection errors from dataTaskWithRequest
. Swift 2 introduced throws
, but you can't throw from Apple's closure because they have no throw support and running async.
我只看到添加返回到我的完成块NSError
的唯一方法,但是据我所知,使用NSError
是旧式的Objective-C方法. ErrorType
仅可用于throws(afaik).
I see only way to add to my completion block NSError
returning, but as I know using NSError
is old-style Objective-C way. ErrorType
can be used only with throws (afaik).
使用Apple网络封盖处理错误的最佳,最现代的方法是什么?据我了解,没有办法在任何异步网络功能中都不会抛出异常吗?
What's the best and most modern method to handle error when using Apple network closures? There is no way no use throws in any async network functions as I understand?
推荐答案
there are many ways you can solve this, but i would recommend using a completion block which expects a Result Enum. this would probably be the most 'Swift' way.
结果枚举恰好具有两个状态,即成功和错误,这对于通常的两个可选返回值(数据和错误)具有很大的优势,这两个返回值会导致4种可能的状态.
the result enum has exactly two states, success and error, which a big advantage to the usual two optional return values (data and error) which lead to 4 possible states.
enum Result<T> {
case Success(T)
case Error(String, Int)
}
在完成块中使用结果枚举可以解决难题.
Using the result enum in a completion block finishes the puzzle.
let InvalidURLCode = 999
let NoDataCode = 998
func getFrom(urlString: String, completion:Result<NSData> -> Void) {
// make sure the URL is valid, if not return custom error
guard let url = NSURL(string: urlString) else { return completion(.Error("Invalid URL", InvalidURLCode)) }
let request = NSURLRequest(URL: url)
NSURLSession.sharedSession().dataTaskWithRequest(request) { data, response, error in
// if error returned, extract message and code then pass as Result enum
guard error == nil else { return completion(.Error(error!.localizedDescription, error!.code)) }
// if no data is returned, return custom error
guard let data = data else { return completion(.Error("No data returned", NoDataCode)) }
// return success
completion(.Success(data))
}.resume()
}
因为返回值是一个枚举,所以应该将其关闭.
because the return value is a enum, you should switch off of it.
getFrom("http://www.google.com") { result in
switch result {
case .Success(let data):
// handle successful data response here
let responseString = String(data:data, encoding: NSASCIIStringEncoding)
print("got data: \(responseString)");
case .Error(let msg, let code):
// handle error here
print("Error [\(code)]: \(msg)")
}
}
另一种解决方案是传递两个完成块,一个用于成功,一个用于错误.类似于:
another solution would be to pass two completion blocks, one for success and one for error. something along the lines of:
func getFrom(urlString: String, successHandler:NSData -> Void, errorHandler:(String, Int) -> Void)
这篇关于在Swift 2中处理异步关闭错误的最佳方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!