简体   繁体   English

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

[英]ios NSURLConnection asynchronous request, displaying data in a UITableView

this question might sound silly but I cant seem to get the idea of asynchronous downloading, parsing and displaying the data. 这个问题可能听起来很傻但我似乎无法获得异步下载,解析和显示数据的想法。 There are a lot of articles about asynchronous parsing and I have read a lot of them, but I didn't find any article about correctly displaying the asynchronously downloaded data. 有很多关于异步解析的文章,我已经阅读了很多文章,但是我没有找到任何关于正确显示异步下载数据的文章。 I have an application that uses a parser to parse a rss feed. 我有一个使用解析器来解析rss feed的应用程序。 At first I used a synchronous request and everything worked well even though the app lagged a little while waiting for the data (obviously). 起初我使用了一个同步请求,一切都运行良好,即使应用程序在等待数据时显然有些滞后(显然)。 The xml parser looks like this: 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

I am initializing the parser in the awakefromnib method like this: self.xmlParser = [[XMLAsynchronousParser alloc] init]; 我在awakefromnib方法中初始化解析器,如下所示: self.xmlParser = [[XMLAsynchronousParser alloc] init];

Calling the start parse method after refreshing: 刷新后调用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];
}

and the cellForRowAtIndexPath method looks like this: 并且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;
    }

The thing is, that the UITableView doesnt show anything after I use the Refresh method. 问题是,在我使用Refresh方法后,UITableView没有显示任何内容。 Am I missing something? 我错过了什么吗?

I did not read all your code, but in general the proper solution is as follows. 我没有阅读您的所有代码,但一般来说,正确的解决方案如下。

1) when you have complete chunks of data, dispatch a block to,the main thread with it. 1)当你有完整的数据块时,用它向主线程发送一个块。 Ask the table for its visible cells, and if the data would change any of them, then update your data model (most likely a mutable array), then reload the table. 询问表格中是否有可见的单元格,如果数据会改变其中任何一个,那么更新数据模型(很可能是一个可变数组),然后重新加载表格。

2) if the data would not be visible just store it in the array. 2)如果数据不可见,只需将其存储在数组中即可。 When the user scrolls the table you can use the data then. 当用户滚动表格时,您可以使用数据。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM