1

我正在为 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:总是 nil。为什么?我究竟做错了什么?

我确实得到了一个 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))}
4

5 回答 5

10

NSCocoaErrorDomain Code=256 实际上表示“原因不明的文件系统或文件 I/O 相关错误”。

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

一般来说,NSDatadataWithContentsOfURL:应该只用于访问本地文件资源。

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

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)你应该得到正确的。

于 2013-08-02T17:14:43.190 回答
2

就我而言,将 AppTransportSecuritySettings 字典添加到 info.plist 并将键 AllowArbitraryLoads 设置为 true。

解决了我的问题...

希望对新开发者有所帮助。

于 2016-01-06T09:45:46.980 回答
1

您的 URL 可能有一个空格,这就是它返回 nil 的原因。只需将 URL 中的空格替换为 '+' :

stringByReplacingOccurrencesOfString:@" " withString:@"+"
于 2014-07-08T09:25:29.127 回答
0

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

于 2015-07-14T16:09:40.037 回答
0

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

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

于 2016-02-21T18:07:30.127 回答