从网页下载大量数据时减少延迟

时间:2012-11-03 04:12:12

标签: objective-c ios multithreading html-parsing

我通过RSS Feed获取数据并在表格视图单元格中显示每篇文章。每个单元格都有一个图像视图,设置为默认图像。如果页面有图像,则图像将替换为文章中的图像。截至目前,每个单元格都会从网页下载源代码,导致应用程序在推送视图控制器和尝试滚动时滞后。

以下是cellForRowAtIndexPath:方法中的内容。

    NSString * storyLink = [[stories objectAtIndex: storyIndex] objectForKey: @"link"];
    storyLink = [storyLink stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
    NSString *sourceCode = [NSString stringWithContentsOfURL:[NSURL URLWithString:storyLink] encoding:NSUTF8StringEncoding error:&error];

    NSString *startPt = @"instant-gallery";
    NSString *startPt2 = @"<img src=\"";

    if ([sourceCode rangeOfString:startPt].length != 0) { //webpage has images
    // find the first  "<img src=...>" tag starting from "instant-gallery"
    NSString *trimmedSource = [sourceCode substringFromIndex:NSMaxRange([sourceCode rangeOfString:startPt])];
    trimmedSource = [trimmedSource substringFromIndex:NSMaxRange([trimmedSource rangeOfString:startPt2])];
    trimmedSource = [trimmedSource substringToIndex:[trimmedSource rangeOfString:@"\""].location];

    NSURL *url = [NSURL URLWithString:trimmedSource];
    NSData *data = [NSData dataWithContentsOfURL:url];
    UIImage *image = [UIImage imageWithData:data];
    cell.picture.image = image;

有人建议使用NSOperationQueue。这会是一个很好的解决方案吗?

编辑:

  dispatch_queue_t someQueue = dispatch_queue_create("cell background queue", NULL);
    dispatch_async(someQueue, ^(void){

        NSError *error = nil;
        NSString * storyLink = [[stories objectAtIndex: storyIndex] objectForKey: @"link"];
        storyLink = [storyLink stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
        NSString *sourceCode = [NSString stringWithContentsOfURL:[NSURL URLWithString:storyLink] encoding:NSUTF8StringEncoding error:&error];

        NSString *startPt = @"instant-gallery";
        NSString *startPt2 = @"<img src=\"";

        if ([sourceCode rangeOfString:startPt].length != 0) { //webpage has images
            // find the first  "<img src=...>" tag starting from "instant-gallery"
            NSString *trimmedSource = [sourceCode substringFromIndex:NSMaxRange([sourceCode rangeOfString:startPt])];
            trimmedSource = [trimmedSource substringFromIndex:NSMaxRange([trimmedSource rangeOfString:startPt2])];
            trimmedSource = [trimmedSource substringToIndex:[trimmedSource rangeOfString:@"\""].location];

            NSURL *url = [NSURL URLWithString:trimmedSource];
            NSData *data = [NSData dataWithContentsOfURL:url];
            UIImage *image = [UIImage imageWithData:data];

            dispatch_async(dispatch_get_main_queue(), ^(void){
                cell.picture.image = image;
            });
        });
        dispatch_release(someQueue);

        return cell;
    }

enter image description here

1 个答案:

答案 0 :(得分:0)

对于可能导致延迟的任何内容,请将其放在后台线程中。当您准备好更新UI​​时,请在主线程上更新它。也许你可以试试GCD -

dispatch_queue_t someQueue = dispatch_queue_create("cell background queue", NULL);
dispatch_async(someQueue, ^(void){

    NSURL *url = [NSURL URLWithString:trimmedSource];
    NSData *data = [NSData dataWithContentsOfURL:url];
    UIImage *image = [UIImage imageWithData:data];

    dispatch_async(dispatch_get_main_queue(), ^(void){
        cell.picture.image = image;
    });
});
dispatch_release(someQueue);

修改

当您有一些可能会降低应用程序速度的进程时,您希望将其放在后台队列中。要将它们放在后台队列中,请使用dispatch_async

dispatch_aysnc(someQueue, ^(void){ 

});

其中someQueue是您创建的后台队列,希望工作完成。但是,与UI相关的任何内容都需要在主队列中,否则可能会发生一些时髦的事情。这就是为什么在dispatch_async内,我们放了另一个dispatch_async。这次,我们指定需要在主队列上更新UI(cell.picture.image):dispatch_get_main_queue()

希望这有点清除它。