首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >目标c/ ios 7从rest获取数据。

目标c/ ios 7从rest获取数据。
EN

Stack Overflow用户
提问于 2014-09-20 16:42:51
回答 1查看 1.7K关注 0票数 0

我想从购物器api(919.html)中获取所有文章,但我不能将数据放入我调用的NSDictionary url:http://myshop.com/api/articles中。

这是我得到的消息来源

代码语言:javascript
复制
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];
                               }

                           }];



}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-09-20 19:49:17

在您的方法中有几件事情需要改进。

首先,这是在主队列上执行网络连接。这是不-不,网络是同步还是不同步。为连接创建一个新的NSOperationQueue并传递它而不是[NSOperationQueue mainQueue]是一个巨大的改进。

第二,错误处理是不正确的。一般来说,目标C的正确错误处理模式是在使用错误之前检查一个调用是否导致了预期的结果。在这种情况下,应该检查的是NSURLResponse,而不是数据。NSURLConnection可能能够很好地连接到remove服务,但是没有返回数据-对于许多HTTP请求,这是预期的,正确的行为。如果存在连接问题,则NSURLResponse将是nil。检查是否响应为零,如果是,然后处理错误。

您也没有检查HTTP响应状态代码或MIME类型。服务器可以响应500,表示服务器错误,或者错误地向您发送HTML (这将使JSON解析器适合)。

下面是一个正确执行上述操作的详细示例。。:

代码语言:javascript
复制
[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

在您的评论中,您指示您正在获得一个带有域NSError和代码-1002-1002。如果您查看NSURLErrors.h,您将看到NSURL错误映射到CFURL错误。如果您查看CFNetworkErrors.h,您可以看到错误代码-1002kCFURLErrorUnsupportedURL。URL加载系统认为您使用的URL不是受支持的类型。这很可能是因为您的URL方案不正确,或者您试图将凭据作为URL的一部分传递的方式是不正确的。在您的评论的其他地方,您指出您正在传递凭据如下:

username:apikey:someurl.com/foo/

这应该更像是:

https://username:apikey@someurl.com/foo/

但是,只有当您正在访问的服务使用的是受支持的HTTP身份验证类型(即基本身份验证)。无论哪种方式,正确地组合URL将修复您当前看到的错误。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25951064

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档