Block_release在后台线程上取消分配UI对象
在WWDC 2010“块和大中央调度”演讲中提出的模式之一是使用嵌套的dispatch_async调用在后台线程上执行耗时的任务,然后在任务完成后更新主线程上的UI
dispatch_async(backgroundQueue, ^{ // do something time consuming in background NSArray *results = ComputeBigKnarlyThingThatWouldBlockForAWhile(); // use results on the main thread dispatch_async(dispatch_get_main_queue(), ^{ [myViewController UpdateUiWithResults:results]; }); });
由于在块内部使用了“myViewController”,它会自动得到一个“保留”,并在清理块之后得到一个“释放”。
如果块的“释放”调用是最终的释放调用(例如,用户在后台任务运行时离开视图),则调用myViewController dealloc方法 – 但是在后台线程调用它!
UIKit对象不喜欢在主线程之外解除分配。 在我的情况下,UIWebView引发一个exception。
这个WWDC如何呈现模式 – 特别提到是避免UIlocking的最佳新方法 – 是如此的有缺陷? 我错过了什么吗?
对于这种情况,您可以使用__block
存储types限定符。 __block
variables不会被块自动保留。 所以你需要自己保留这个对象:
__block UIViewController *viewController = [myViewController retain]; dispatch_async(backgroundQueue, ^{ // Do long-running work here. dispatch_async(dispatch_get_main_queue(), ^{ [viewController updateUIWithResults:results]; [viewController release]; // Ensure it's released on main thread } });
编辑
使用ARC,__blockvariables对象被块自动保留,但是我们可以设置nil值给__blockvariables来释放被保留的对象。
__block UIViewController *viewController = myViewController; dispatch_async(backgroundQueue, ^{ // Do long-running work here. dispatch_async(dispatch_get_main_queue(), ^{ [viewController updateUIWithResults:results]; viewController = nil; // Ensure it's released on main thread } });
在一个线程中,我只使用[viewController retain];
那么在线程的末尾使用[viewController release]
。 它工作,我不使用GCD~
这对我工作(添加一个计时器):
[self retain]; // this guarantees that the last release will be on the main threaad dispatch_async(backgroundQueue, ^{ // do something time consuming in background NSArray *results = ComputeBigKnarlyThingThatWouldBlockForAWhile(); // use results on the main thread dispatch_async(dispatch_get_main_queue(), ^{ [myViewController UpdateUiWithResults:results]; [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(releaseMe:) userInfo:nil repeats:NO]; }); }); - (void)releaseMe:(NSTimer *)theTimer { [self release]; // will be on the main thread }
- Swift 3:DispatchQueue.main.async {}和DispatcQueue.main.async之间的区别(execute:{})?
- Grand Central Dispatch中的线程限制解决方法?
- Swift中的“暂停”游戏
- 如果我嵌套dispatch_async调用会发生什么?
- 主线程在viewDidLoad中的一个并发队列上执行dispatch_async,或者在一个方法内部执行
- 这是比较两个GCD队列的正确方法吗?
- 问题与GCD和太多的线程
- 核心数据和GCD:将正确的托pipe对象上下文传递给自定义NSManagedObjects
- 混合同步/asynchronous与串行/并发队列时,调度程序如何工作?