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

时间:2013-08-02 15:17:40

标签: ios json nsdata

我正在为Stack Exchange API制作iOS客户端。经过漫长的战斗,我终于设法实现了身份验证 - 这给了我一个令牌,我坚持使用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))}

5 个答案:

答案 0 :(得分:9)

NSCocoaErrorDomain Code = 256实际上意味着“文件系统或文件I / O相关错误,其原因未知”。

为什么会出现此错误可能是因为使用dataWithContentsOfURL:无法使用该远程URL - 或者可能是因为包含身份验证和令牌的查询参数。因此,您会收到“奇怪”错误。

通常,NSData的dataWithContentsOfURL:应仅用于访问本地文件资源。

为了解决您的问题,您应该分两步改进代码:

1)使用NSURLConnection的方便类方法

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

当请求完成时,该块定义了用于响应数据。通常,首先检查错误参数,然后检查响应的状态代码和Content-type - 按此顺序。

2)用您自己的实例方法(或来自第三方的方法)替换前者,使用类似的签名但更复杂。

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

  • 取消
  • 在各方面自定义身份验证
  • 将正文数据加载到文件
  • 处理同时收到的块
  • 在队列中执行多个请求,控制同时连接的数量

还有几个。

方法#2通常被实现为NSOperation的子类,并封装了NSURLConnection 对象(您需要取消连接)。

您将找到如何在实现委托的异步模式下使用NSURLConnection的答案。此外,还有第三方解决方案。

您可能会发现官方文档非常宝贵: Using NSURLConnection

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

SimpleGetHTTPRequest

此类不基于NSOperation,但可以轻松修改。请参阅NSOperation的官方文档,了解如何创建子类。这基本上很容易,但有一些重要的事情(KVO),你应该得到正确的。

答案 1 :(得分:2)

在我的例子中,将AppTransportSecuritySettings字典添加到info.plist并将密钥AllowArbitraryLoads设置为true。

解决了我的问题...

希望它能帮助新开发者。

答案 2 :(得分:1)

您的网址可能有一个空格,这就是它返回nil的原因。只需用“+”替换网址中的空格:

stringByReplacingOccurrencesOfString:@" " withString:@"+"

答案 3 :(得分:0)

当我更改文件夹结构时出现此问题。它为我提供了其他NSError代码,例如512和4,用于任何文件操作(本地和Web)。解决方案是删除我的IOS Simulator文件夹(Library \ Developer \ CoreSimulator)。

答案 4 :(得分:0)

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

其根本原因可能实际上是您的应用传输安全设置"。默认情况下,iOS不允许任意加载URL。