【问题标题】:ios NSURLConnection asynchronous request, displaying data in a UITableViewios NSURLConnection 异步请求,在 UITableView 中显示数据
【发布时间】:2013-05-17 06:04:28
【问题描述】:

这个问题可能听起来很傻,但我似乎无法理解异步下载、解析和显示数据的想法。有很多关于异步解析的文章,我也看了很多,但是我没有找到任何关于正确显示异步下载数据的文章。 我有一个使用解析器来解析 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 没有显示任何内容。我错过了什么吗?

【问题讨论】:

    标签: ios asynchronous xml-parsing


    【解决方案1】:

    我没有阅读你所有的代码,但总的来说正确的解决方案如下。

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

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

    【讨论】:

    • 我最终使用自定义委托来通知 VC 解析。
    猜你喜欢
    • 1970-01-01
    • 2011-08-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多