我想从shopware API获取所有文章(http://wiki.shopware.de/Shopware-API_cat_919.html) 但我没有将数据放入
NSDictionary
。
我调用的网址:http://myshop.com/api/articles.
这是我的来源:
NSURL *url = [NSURL URLWithString:weburl];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[NSURLConnection sendAsynchronousRequest:request
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse *response,
NSData *data, NSError *connectionError) {
if (data.length > 0 && connectionError == nil) {
NSDictionary *rest_data = [NSJSONSerialization JSONObjectWithData:data
options:0
error:NULL];
_newsDataForTable = [NSMutableArray array];
NSDictionary *news;
for (id key in rest_data[@"postalcodes"]) {
news = [rest_data[@"postalcodes"] objectForKey:key];
}
int iterator = 0;
for (id key in news) {
[_newsDataForTable insertObject:key[@"title"] atIndex:iterator];
iterator++;
}
[_newsTable reloadData];
[_newsTable numberOfRowsInSection:[_newsDataForTable count]];
[_newsTable reloadRowsAtIndexPaths:0 withRowAnimation:UITableViewRowAnimationLeft];
}
}];
}
首先,这是在主队列上执行联网。无论网络是否同步,这是一个禁忌。为您的连接创建一个新的
NSOperationQueue
并传递它而不是 [NSOperationQueue mainQueue]
是一个巨大的进步。
第二,错误处理不正确。一般来说,Objective-C 的正确错误处理模式是在使用错误之前检查调用是否产生了预期的结果。在这种情况下,应该检查的是
NSURLResponse
,而不是数据。 NSURLConnection 可能能够很好地连接到删除服务,但无法返回数据 - 对于许多 HTTP 请求来说,这是预期的正确行为。如果连接出现问题,NSURLResponse
将会是 nil
。检查响应是否为零,如果是则处理错误。
您也没有检查 HTTP 响应状态代码或 MIME 类型。服务器可能会响应 500,指示服务器错误,或者可能错误地向您发送 HTML(这会使 JSON 解析器适合)。
[NSURLConnection sendAsynchronousRequest:request queue:[self connectionQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
if (response != nil){
if ([[self acceptableStatusCodes] containsIndex:[(NSHTTPURLResponse *)response statusCode] ]){
// The server responded with an HTTP status code that indicates success
if ([[self acceptableMIMETypes] containsObject:[[response MIMEType] lowerCaseString] ]){
// The server responded with a MIME type we can understand.
if ([data length] > 0){
NSError *jsonError = nil;
id jsonObject = nil;
// The server provided data in the response, which means we can attempt to parse it
// Note that we are not specifying NSJSONReadingMutableContainers or NSJSONReadingMutableLeaves, as this would result in
// an object that is not safe to use across threads.
jsonObject = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:&jsonError];
if (jsonObject != nil){
// The JSON parser successfully parsed the data, and returned an object. There is nothing to tell us what kind of object was returned.
// We need to make sure it responds to the selectors we will be using - ideally, we'd pass this object to a method that takes an
// id parameter, not NSDictionary, and inside that method it would check wether the id object responds to the specific selectors
// it is going to use on it.
if ([jsonObject respondsToSelector:@selector(dictionaryWithDictionary:)]){
[self doStuffWithDictionary:jsonObject];
}
} else {
// The JSON parser was unable to understand the data we provided, and the error should indicate why.
[self presentError:jsonError];
}
} else {
// The server responded with data that was zero length. How you deal with this is up to your application's needs.
// You may create your own instance of NSError that describes the problem and pass it to your error handling, etc.
}
} else {
// The server response was a MIME type we could not understand. How you handle this is up to you.
}
} else {
// The server response indicates something went wrong: a 401 Not Found, etc.
// It's up to your application to decide what to do about HTTP statuses that indicate failure.
// You may create your own instance of NSError that describes the problem and pass it to your error handling, etc.
}
} else {
// Only inspect the error parameter if the response is nil.
// The error indicates why the URL loading system could not connect to the server.
// It is only valid to use this error if the server could not connect - which is indicated by a nil response
[self presentError:connectionError];
}
}];
// Returns the HTTP status codes we find acceptable.
- (NSIndexSet *) acceptableStatusCodes {
return [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(200, 99)];
}
// Returns the mime types we can accept and understand.
- (NSSet *) acceptableMimeTypes {
NSSet *result = nil;
result = [NSSet setWithObjects:@"application/json", @"application/json; charset=utf-8", nil];
return result;
}
// Generic error handling method.
- (void) presentError:(NSError *)error {
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
}];
}
是的,这是很多代码,应该将其分解为更小的方法 - 但它说明了应该实现的逻辑。
在您的评论中,您表明您获得的是
NSError
,域名为 NSURLErrorDomain
,代码为 -1002
。如果您查看 NSURLErrors.h,您将看到 NSURL 错误映射到 CFURL 错误。如果您查看 CFNetworkErrors.h,您可以看到错误代码 -1002
是 kCFURLErrorUnsupportedURL
。 URL 加载系统认为您使用的 URL 不是受支持的类型。这很可能是因为您的 URL 的方案不正确,或者您尝试将凭据作为 URL 的一部分传递的方式不正确。在您的评论中的其他地方,您表明您正在传递凭据,如下所示:
username:apikey:someurl.com/foo/
哪个应该更像:
https://username:[email protected]/foo/
但前提是您正在访问的服务使用受支持的 HTTP 身份验证类型(即基本身份验证)。无论哪种方式,正确编写 URL 将修复您当前看到的错误。