你如何从dataTaskWithURL的NSURLResponse获取状态代码?

pat*_*ick 4 objective-c nshttpurlresponse nsurlsession

我正在使用Apple的NSURLSession#dataTaskWithURL方法执行一个简单的get请求

[[mySession dataTaskWithURL:myUrl completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
   // fancy code goes here...
 }] resume];
Run Code Online (Sandbox Code Playgroud)

如果我想有条件做某事,如果状态代码成功,似乎我必须将NSURLResponse转换为NSHTTPURLResponse .....

    NSUInteger statusCode = ((NSHTTPURLResponse *)response).statusCode;
    if (!error && statusCode == 200) {
      // even fancier code goes here
    } else {
      // omg!!!!!!!!!
    }
Run Code Online (Sandbox Code Playgroud)

...

但是----------我的问题是:为什么!?!?!?!?!?!?!?

为什么Apple会将响应对象传递给一个不知道自己状态的类型?!我必须编写这段代码的事实让我觉得我做的事情非常错误,必须有一个更好的方法来知道它是200,404还是500 ......

我希望我可以将completionHandler的块参数类型更改为NSHTTPURLResponse,但这似乎是不行的!

Mat*_*son 7

协议设计如果做得好,总是关注未来.

虽然我们现在只使用NSURLSession for HTTP,但将来有可能将其用于其他网络协议.例如,如果你可以在某些时候将它用于FTP,那就不会让我感到惊讶.

使用一个简单的响应基类作为完成块/委托参数,并根据您所知道的网络协议进行转换,为将来提供NSURLSession灵活性.

如果一个新的网络协议出现了不同的需求 - 也许它的响应中甚至没有整数状态代码,比如说 - Apple可以添加NSURLResponse的另一个子类,并保留其他所有内容,包括完成处理程序的签名块和所有NSURLSession*Delegate协议.

如果他们"硬编码"了要使用的网络协议和完成处理程序块NSHTTPURLResponse,那么如何将新的网络协议(例如FTP)干净地添加到NSURLSession?

(注意:通过"协议",而不是"网络协议" - 我在这个答案中使用两个术语 - 我的意思是NSURLSession类的接口设计,包括它们的实际协议和等效的完成处理程序.)