如果调用对象被释放,调度线程会发生什么?

时间:2012-04-18 21:17:04

标签: objective-c uitableview grand-central-dispatch

我将图像异步加载到UITableView中的单元格上。代码如下:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{

// after getting the cell..

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSString *imageUrl = [someMethodToGetImageUrl];
        NSData *imageData = [[NSData alloc] initWithContentsOfURL:[NSURL imageUrl]];
        dispatch_async(dispatch_get_main_queue(), ^{
            cell.imageView.image = [UIImage imageWithData:imageData];
            [tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationNone];
        });
    });

}

我的问题涉及如果在激活调度之后但在线程完成尝试设置单元格图像之前释放此tableView(例如,从navigationController堆栈中弹出)会发生什么。该单元格也将被解除分配,并且尝试对该单元格执行操作会导致崩溃,不是吗?

我上面的代码一直在崩溃。如果我进入这个tableView然后立即退出,我就会崩溃:

[tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationNone];

如果我将其更改为:

[self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationNone];
崩溃消失了,这对我来说真的没有意义。有人可以向我解释为什么会这样吗?感谢。

1 个答案:

答案 0 :(得分:2)

任何可能使块超出其原始范围的例程都需要复制它。 dispatch_async()确实如此。

复制块时,它会保留它引用的任何对象指针变量。如果块以实例变量的形式隐式访问self,则它保留self。它保留了这些引用,直到它自己被释放。

在您的示例中,cellimageDataindexPathtableView都会保留,直到完成。