NSData dataWithContentsOfURL:不返回浏览器中显示的URL的数据

我正在为Stack Exchange API制作iOS客户端。 经过漫长的斗争之后,我终于设法实现了身份validation – 这为我提供了一个令我坚守的URL。 当令牌有效时,URL如下所示:

https://api.stackexchange.com/2.1/me/associated?key=_____MY_SECRET_KEY______&access_token=_____ACCESS_TOKEN_:)_____ 

这个在合法的时候会把我带到这个JSON的网页中:

 {"items":[{"site_name":"Stack Overflow","site_url":"http://stackoverflow.com","user_id":1849664,"reputation":4220,"account_id":1703573,"creation_date":1353769269,"badge_counts":{"gold":8,"silver":12,"bronze":36},"last_access_date":1375455434,"answer_count":242,"question_count":26},{"site_name":"Server Fault","site_url":"http://serverfault.com","user_id":162327,"reputation":117,"account_id":1703573,"creation_date":1362072291,"badge_counts":{"gold":0,"silver":0,"bronze":9},"last_access_date":1374722580,"answer_count":0,"question_count":4},... 

我用这个代码得到正确的JSON:

 NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"https://api.stackexchange.com/2.1/me/associated?key=__SECRET_KEY_:)__&access_token=%@", [[NSUserDefaults standardUserDefaults] objectForKey:@"token"]]]; NSData *jsonData = [NSData dataWithContentsOfURL:url]; if (jsonData) { NSDictionary *JSON = [NSJSONSerialization JSONObjectWithData:jsonData options:kNilOptions error:nil]; } 

但是,当手动使令牌无效时,URL仍然看起来相同,浏览器中的页面显示如下:

 {"error_id":403,"error_name":"access_denied","error_message":"`key` is not valid for passed `access_token`, token not found."} 

但是, dataWithContentsOfURL:始终为零 。 为什么? 我究竟做错了什么?

我得到一个NSError返回:

 Error Domain=NSCocoaErrorDomain Code=256 "The operation couldn't be completed. (Cocoa error 256.)" UserInfo=0x1dd1e9f0 {NSURL=https://api.stackexchange.com/2.1/me/associated?key=key((&access_token=to‌​ken))} 

NSCocoaErrorDomain Code = 256实际上是指“原因未知的文件系统或文件I / O相关的错误”。

为什么你得到这个错误很可能是因为使用dataWithContentsOfURL:将不能使用该远程URL – 或者可能是因为包含身份validation和令牌的查询参数。 因此,你会得到“怪异”的错误。

一般来说,NSData的dataWithContentsOfURL:只能用于访问本地文件资源。

为了解决你的问题,你应该分两步来改善你的代码:

1)使用NSURLConnection的方便的类方法

+ (void)sendAsynchronousRequest:(NSURLRequest *)request queue:(NSOperationQueue *)queue completionHandler:(void (^)(NSURLResponse*, NSData*, NSError*))handler

该块定义了请求完成后如何处理响应数据。 一般来说,首先检查错误参数,然后检查响应的状态代码和内容types – 按此顺序。

2)用自己的实例方法(或来自第三方的实例方法)replace前者,并使用相似的签名,但要复杂得多。

方法#2使您能够实施和使用以下重要function

  • 消除
  • 定制各方面的authentication
  • 将主体数据加载到文件
  • 进程同时收到块
  • 在控制同时连接数量的队列中执行多个请求

还有一些。

方法#2经常被实现为NSOperation一个子类,并封装NSURLConnection 对象 (你需要取消连接)。

你会find如何在asynchronous模式下使用NSURLConnection实现委托的答案。 另外,还有第三方解决scheme。

你可能会发现这个官方文档也是非常宝贵的: 使用NSURLConnection

为了快速入门,您可以看看我的Gist上的“简单GET请求”类:

SimpleGetHTTPRequest

这个类不是基于NSOperation ,但它可以很容易地修改。 请参考NSOperation的官方文档如何创build一个子类。 这基本上是容易的,但有一些重要的事情(KVO),你应该得到正确的。

在我的情况下,将AppTransportSecuritySettings字典添加到info.plist并将AllowArbitraryLoads设置为true。

解决了我的问题…

希望它能帮助新开发者。

您的url可能有一个空格,这就是为什么它返回零。只需用“+”replaceURL中的空格即可:

 stringByReplacingOccurrencesOfString:@" " withString:@"+" 

当我更改文件夹结构时遇到了这个问题。 它给了我其他NSError代码,如512和4的任何文件操作(本地和networking)。 解决办法是删除我的IOS模拟器文件夹(Library \ Developer \ CoreSimulator)。

如果您尝试通过HTTP访问远程URL并使用XCode 7或更高版本,则可能会从[NSData dataWithContentsOfURL:]返回一个NSCocoaErrorDomain。

这可能是您的“应用程序传输安全设置”的根本原因。 默认情况下,iOS不允许任意加载URLS。