Ios 更新dispatch_get_main_queue()上的UI

Ios 更新dispatch_get_main_queue()上的UI,ios,grand-central-dispatch,Ios,Grand Central Dispatch,我有一个问题与使用队列更新主线程上的UI有关 好吧,假设我们创建了一个UITableView,它用UIImageView显示UILabel。UIImage在prepareCellfor中异步加载。。使用: dispatch_async(t_queue, ^{ //load image //dispatch_async(dispatch_get_main_queue(),^{ cell.imageView = image; } }); 但是,当块获取图像时,用户按

我有一个问题与使用队列更新主线程上的UI有关

好吧,假设我们创建了一个UITableView,它用UIImageView显示UILabel。UIImage在prepareCellfor中异步加载。。使用:

 dispatch_async(t_queue, ^{
   //load image
   //dispatch_async(dispatch_get_main_queue(),^{
     cell.imageView = image;
   }
 });
但是,当块获取图像时,用户按下一个单元格(或导航视图控制器上的“后退”按钮)该单元格的load de DetailViewController(或返回应用程序)

我的问题是:当块启动主线程来更新单元格的imageView时会发生什么?它正在尝试更新一个未加载到窗口中的UIView,甚至它可能已被卸载


谢谢这是个好问题。当使用
ARC
时,答案基本上是块本身保留了对象,因此它将在以后出现。这是一个微妙的记忆陷阱。如果此单元格来自的
UITableView
被取消分配并释放其所有单元格,则此单元格将被保留(尽管在屏幕外),并具有
cell.imageView=image的分配完成,然后它将被释放

我非常喜欢受控实验,并开始测试这一点,但是
UITableView
有许多活动部分(没有双关语)。因此,我创建了一个非常简单的实验,使用一个简单的
NSObject
子类,如下所示:

@implementation SayHello
-(void)sayHello{
    NSLog(@"Hello");
}
-(void)dealloc{
    NSLog(@"SayHello dead");
}
@end
显然,这个类的目的是给我一个在块中调用的函数(
sayHello
),并在取消分配时生成一个
NSLog

我是这样进行测试的:

SayHello *hello = [[SayHello alloc] init];
dispatch_async(dispatch_get_global_queue(0, 0), ^{
    double delayInSeconds = 30.0;
    dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
    dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
        [hello sayHello];
    });
});
30秒即使是最懒的运行循环时间也可以释放“hello”对象(如果实际上它没有被保留)。但在这30秒钟里,控制台是无声的。30秒过后,我立即收到“Hello”,然后是“SayHello dead”消息

那么这怎么是“抓住你了”?很明显,如果你没有意识到积木/弧线在做这件事,它最终可能会留下你认为应该消失的东西。但也可以使用您的
UITableViewCell
示例;如果您的单元格只显示一次,并通过网络发送图像请求,但当块等待图像时,单元格被重用,该怎么办?现在有第二个块,它引用了试图设置其图像的单元格。好吧,现在你有一场比赛,失败者将决定显示什么图像