在Swift 2中处理异步关闭错误的最佳方法? [英] Best way to handle errors from async closures in Swift 2?

查看:70
本文介绍了在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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆