ios NSURLConnection异步请求,在UITableView中显示数据

标签 ios asynchronous xml-parsing

这个问题听起来可能很愚蠢,但我似乎无法理解异步下载、解析和显示数据的想法。关于异步解析的文章很多,我也看了很多,但是没有找到一篇关于正确显示异步下载数据的文章。 我有一个使用解析器解析 rss 提要的应用程序。起初我使用了一个同步请求并且一切都运行良好,即使应用程序在等待数据时有点滞后(很明显)。 xml 解析器如下所示:

#import "XMLAsynchronousParser.h"
@implementation XMLAsynchronousParser
@synthesize itemList;
-(void)startParse:(NSString *)url{
parsing = YES;
receivedData = [[NSMutableData alloc] init];
itemList = [[NSMutableArray alloc] init];
errorParsing = NO;

NSLog(@"PARSING from url:\n%@",url);
NSString *agentString = @"Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_6; en-us) AppleWebKit/525.27.1 (KHTML, like Gecko) Version/3.2.1 Safari/525.27.1";

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]];

[request setValue:agentString forHTTPHeaderField:@"User-Agent"];

NSURLConnection *urlConnection = [NSURLConnection connectionWithRequest:request delegate:self];
[urlConnection start];
}

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{
[receivedData setLength:0];
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{
[receivedData appendData:data];
}


- (void)connectionDidFinishLoading:(NSURLConnection *)connection{
    NSLog(@"Connection did finish loading");
    rssParser = [[NSXMLParser alloc] initWithData:receivedData];
    [rssParser setDelegate:self];
    [rssParser parse];

    parsing = NO;
}


- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{
    NSLog(@"Asynchronous parsing did end with error:\n%@",[error description]);
}

#pragma Mark - parsing methods

- (void)parserDidStartDocument:(NSXMLParser *)parser{
    NSLog(@"FILE found and parsing started.");
}

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict{

    currentElement = [elementName copy];
    elementValue = [[NSMutableString alloc] init];
    if([currentElement isEqualToString:@"item"]){
        item = [[NSMutableDictionary alloc] init];
    }
}

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{

    if([elementName isEqualToString:@"item"]){
        [itemList addObject:[item copy]];
    }else{
        [item setObject:elementValue forKey:elementName];
    }
}

@end

我在 awakefromnib 方法中初始化解析器,如下所示:self.xmlParser = [[XMLAsynchronousParser alloc] init];

刷新后调用start parse方法:

- (void)dropViewDidBeginRefreshing{
    NSArray *filters = [[NSArray alloc] init];
    NSMutableArray *itemList = [[NSMutableArray alloc] init];

    filters = [self.dataController selectSelectedFilters];

    for (BazosAgentFilter *filter in filters) {
        NSString *url = [self.dataController createURLfromFilter:filter];
        [self.xmlParser startParse:url];

        for (NSDictionary *item in self.xmlParser.itemList) {
            NSString *title = [item objectForKey:@"title"];
            NSString *description = [item objectForKey:@"description"];
            NSString *pubdate = [item objectForKey:@"pubDate"];
            NSString *link = [item objectForKey:@"link"];
            BazosAgentItem *bazosItem = [[BazosAgentItem alloc] initWithTitle:title
                                                                  description:description
                                                                         link:link
                                                                      pubdate:pubdate
                                                                     filterId:filter.filter_id];
            [self.dataController addBazosAgentItem:bazosItem];
        }

        [itemList addObjectsFromArray:[self.dataController selectItemsFromDatabaseWithFilterId:[filter.filter_id integerValue]]];
    }
    self.itemList = itemList;
    [self.tableView reloadData];
    [self.refreshControl endRefreshing];
}

cellForRowAtIndexPath 方法如下所示:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    NSLog(@"###cell for row!");

    NSString *cellIdentifier = @"BazosItemCell";
    ItemTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];

    BazosAgentItem *item = [self.itemList objectAtIndex:indexPath.row];
    NSLog(@"ITEM LINK: %@",item.link);

    NSString *itemTitle = item.title;
    NSString *itemID = [self parseItemID:item.link];
    NSString *itemIDpostfix = [itemID substringFromIndex:(itemID.length-3)];
    NSString *itemImageString = [NSString stringWithFormat:@"http://www.bazos.sk/img/1/%@/%@.jpg",itemIDpostfix,itemID];
    NSURL *itemImageUrl = [NSURL URLWithString:itemImageString];

    [cell.itemImage setImageWithURL:itemImageUrl];
    cell.itemImage.contentMode = UIViewContentModeScaleAspectFit;

    cell.firstLabel.text = itemTitle;

    [cell sizeToFit];
    return cell;
    }

问题是,在我使用 Refresh 方法后,UITableView 没有显示任何内容。我错过了什么吗?

最佳答案

我没有阅读您的所有代码,但通常正确的解决方案如下。

1) 当你有完整的数据 block 时,将一个 block 分派(dispatch)给主线程。向表格询问其可见单元格,如果数据会更改其中任何一个,则更新您的数据模型(很可能是可变数组),然后重新加载表格。

2) 如果数据不可见,则将其存储在数组中。当用户滚动表格时,您就可以使用数据了。

关于ios NSURLConnection异步请求,在UITableView中显示数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16687502/

相关文章:

ios - 在同步调用中执行异步任务

Javascript - 异步函数完成后如何等待执行下一行?

java - ProgressMonitorDialog 和用户交互

c# - 如何将文件编码从 windows-1251 更改为 utf-8

java - 使用 Jersey 在 Java RESTful Web 服务中生成 JSON 和 XML 响应

ios - 是否可以通过编程方式创建 unwind segue?

iphone - iOS 键盘是否可编程(适用于 App Store 应用程序)?

c# - 如何使用 XmlReader 及其结束标记解析 XML?

ios - UI界面方向问题

ios - 如何使用 Shinobi iOS SDK 将图表轴链接到图表系列?