0

我有以下代码尝试异步加载表格视图中的一行缩略图:

for (int i = 0; i < totalThumbnails; i++)
{
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), 
    ^{
        __block GraphicView *graphicView;
        __block Graphic *graphic;

        dispatch_async(dispatch_get_main_queue(), 
        ^{
            graphicView = [[tableViewCell.contentView.subviews objectAtIndex:i] retain];
            graphic = [[self.thumbnailCache objectForKey: [NSNumber numberWithInt:startingThumbnailIndex + i]] retain];

            if (!graphic)
            {
                graphic = [[self graphicWithType:startingThumbnailIndex + i] retain];
                [self.thumbnailCache setObject: graphic forKey:[NSNumber numberWithInt:startingThumbnailIndex + i]];
            }

            [graphicView setGraphic:graphic maximumDimension:self.cellDimension];
        });

        [graphicView setNeedsDisplay];

        dispatch_async(dispatch_get_main_queue(), 
        ^{
            CGRect graphicViewFrame = graphicView.frame;
            graphicViewFrame.origin.x = ((self.cellDimension - graphicViewFrame.size.width) / 2) + (i * self.cellDimension);
            graphicViewFrame.origin.y = (self.cellDimension - graphicViewFrame.size.height) / 2;
            graphicView.frame = graphicViewFrame;
        });

        [graphicView release];
        [graphic release];
    });

}

但是,当我运行代码时,我在这一行的访问权限不好:[graphicView setNeedsDisplay];值得一提的是,当我这样设置代码时,代码工作正常:

for (int i = 0; i < totalThumbnails; i++)
{
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), 
    ^{
        dispatch_async(dispatch_get_main_queue(), 
        ^{
              //put all the code here
        });
}

它工作正常,并且在UITableView第一次调用时异步加载,但是滚动仍然非常不稳定。

所以我想让第一个代码工作,这样我就可以在全局线程而不是主线程中完成绘图(我假设这会修复不连贯的滚动?)。

由于 iOS4 绘图能够异步完成,所以我不认为这是问题所在。可能我在滥用__Block类型?

有谁知道我怎样才能让它工作?

4

2 回答 2

2

你完全误解了如何使用 GCD。查看您的代码:

        __block GraphicView *graphicView;

您在此处的变量未初始化为零。向其发送消息是不安全的。

        __block Graphic *graphic;

        dispatch_async(dispatch_get_main_queue(), 
        ^{
            //statements
        });

您在此处的调度语句会立即返回。该系统可让您在不同的线程上执行此任务。在执行上述语句之前,或者可能同时执行上述语句,我们在此处继续执行下一行...

        [graphicView setNeedsDisplay];

此时,图形视图可能已由您上面的调度语句初始化,也可能未初始化。很可能不会,因为没有时间。由于它还没有被初始化,它指向随机内存,因此尝试向它发送消息会导致 EXC_BAD_ACCESS。

如果您想异步绘制单元格内容(或预渲染图像等)。我强烈建议您观看WWDC 2012会议 211“在 iOS 上构建并发用户界面”。他们几乎完全按照您似乎正在尝试做的事情,并解释了您可能遇到的所有陷阱。

于 2012-10-30T09:32:16.080 回答
0

UIView我认为问题是因为您试图在工作线程上重新绘制。你应该移动这个:

[graphicView setNeedsDisplay];

到主队列。

于 2012-10-30T09:00:58.880 回答