我有一个问题与使用队列在主线程上更新UI有关.
那么,假设我们创建了一个UITableView,它显示了一个带有UI@L_301_0@View的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秒给出最懒惰的runloop时间来释放“hello”对象(如果实际上没有保留).但是对于这30秒,控制台是静音的. 30秒过后,我会立即收到“Hello”,然后点击“SayHello dead”消息.
那么这是一个“骗子”呢?嗯,显然如果你没有意识到Block / ARC正在做这件事,那么可能会最终保持你以为应该去的东西.而且你的例子是UITableViewCell;如果您的单元格显示一次并通过网络向图像发送请求,但是当块等待图像时,单元格被重用?现在有一个第二个块参考该单元格尝试设置其图像.那么现在你有一个比赛,失败者会决定显示什么图像.