在单独的线程上加载表值

时间:2012-10-15 23:19:13

标签: iphone ios cocoa-touch parallel-processing grand-central-dispatch

我有以下代码:

dispatch_async(dispatch_get_global_queue(0, 0), ^
{
    [self loadThumbnails]; //loads an array of photos which get loaded into each table cell
    [self performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:NO];
});

在我的子类UITableView的初始值设定项中。我希望表格能够在单独的线程上加载这些缩略图,因为它们需要一些时间来加载。然而,当我执行上面的代码时,tableview显示为空白。所以我的第一个问题是如何解决这个问题?

我的第二个问题是,我希望一旦tableview对象被释放,就会杀死这个调度队列。这有可能/如何实现?

尝试从Vikings实施解决方案,这就是我所得到的:

- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{
    static NSString *cellIdentifier = @"ThumbnailCell";
    UITableViewCell *tableViewCell = [self dequeueReusableCellWithIdentifier:cellIdentifier];    

    if (!tableViewCell)
    {
        tableViewCell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier] autorelease];
    }


    NSInteger thumbnailsPerCell = self.thumbnailViewsPerCell;
    NSInteger startingThumbnailIndex = indexPath.row * thumbnailsPerCell;
    NSInteger totalThumbnails = MIN(((indexPath.row * thumbnailsPerCell) + thumbnailsPerCell) , [self.thumbnailViews count]) - startingThumbnailIndex;

    if ([tableViewCell.contentView subviews])
    {
        for (UIView *subview in [tableViewCell.contentView subviews]) 
        {
            [subview removeFromSuperview];
        }
    }

    for (int i = 0; i < totalThumbnails; i++)
    {
        UIView *thumbnailView = [[UIView alloc] initWithFrame:CGRectMake(i * self.cellDimension, 0, self.cellDimension, self.cellDimension)];
        UIView *thumbnail = [[self.thumbnailCache objectForKey:[NSNumber numberWithInt:i]] retain];
        if (thumbnail)
        {
            [thumbnailView addSubview:thumbnail];
            [tableViewCell.contentView addSubview:thumbnailView];
            [thumbnailView release];
            [thumbnail release];
        }
        else 
        {
            dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), 
            ^{
                UIView *thumbnail = [[self createThumbnailAtIndex:i] retain];

                if (thumbnail)
                {
                    dispatch_async(dispatch_get_main_queue(), 
                    ^{
                        UITableViewCell *tableViewCell = [self cellForRowAtIndexPath:indexPath];

                        if (tableViewCell)
                        {
                            [thumbnailView addSubview:thumbnail];
                            [tableViewCell.contentView addSubview:thumbnailView];
                            [thumbnailView release];
                            [thumbnail release];
                        }
                    });

                    [self.thumbnailCache setObject:thumbnail forKey:[NSNumber numberWithInt:i]];
                }
            });
        }
    }

    return tableViewCell;
}

这是一个空白的tableView。任何线索为什么?

3 个答案:

答案 0 :(得分:1)

将GCD与performSelector混合有点奇怪。我会这样做:

dispatch_async(dispatch_get_global_queue(0, 0), ^
{
    [self loadThumbnails]; //loads an array of photos which get loaded into each table cell
    dispatch_async(dispatch_get_main_queue(), ^ {
        [self reloadData];
    });
});

答案 1 :(得分:1)

我有同样的问题,并且完美地解决了它,检查下面的主题。只需在单独的线程中加载图像,这种技术称为延迟加载。

Table View Scrolling Async

答案 2 :(得分:0)

回答你的第二个问题: 也许你不应该为你的桌子加载所有缩略图。只需加载您需要在单独的请求中显示的那些。如果单元格已更改缩略图图像,您甚至可以取消先前的请求。 甚至还有一些库可以为您完成所有事情,例如SBWebImage

相关问题