相关疑难解决方法(0)

Block_release在后台线程上释放UI对象

WWDC 2010"Blocks and Grand Central Dispatch"演讲中提出的模式之一是使用嵌套的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];
    });
});
Run Code Online (Sandbox Code Playgroud)

由于"myViewController"正在块中使用,它会自动获得"保留",并在清除块时稍后获得"释放".

如果块的'release'调用是最终的释放调用(例如,用户在后台任务运行时导航远离视图),则调用myViewController dealloc方法 - 但是它在后台线程上调用!!

UIKit对象不喜欢在主线程之外取消分配.在我的例子中,UIWebView抛出异常.

这个WWDC如何呈现模式 - 特别提到避免UI锁定的最佳新方法 - 是如此有缺陷?我错过了什么吗?

grand-central-dispatch ios objective-c-blocks

17
推荐指数
1
解决办法
4217
查看次数

dealloc在使用ARC构建的后台GCD队列崩溃应用程序上调用

我有一个视图控制器,可以在后台GCD队列中下载资产.我将下载函数传递给回调块,以便在下载完成后执行,并且它总是在主线程上执行此块.

如果我的视图控制器在下载完成之前被用户解雇,则会出现此问题.我怀疑发生了什么,一旦我的视图控制器被解除,回调块是唯一保留对控制器的强引用的东西.回调块仅保留在后台线程中,因此一旦释放,回调块范围内捕获的所有对象也将被释放,尽管在后台队列中.

这就是问题:在后台队列中释放会导致dealloc在同一队列中运行,而不是在主队列中运行.反过来,这会dealloc在后台调用,应用程序崩溃:

2012-01-19 12:47:36.349 500px iOS[4892:12107] bool _WebTryThreadLock(bool), 0x306c10: Tried to obtain the web lock from a thread other than the main thread or the web thread. This may be a result of calling to UIKit from a secondary thread. Crashing now...
[Switching to process 16643 thread 0x4103]
[Switching to process 16643 thread 0x4103]
(gdb) where
#0  0x307fd3c8 in _WebTryThreadLock ()
#1  0x307ff1b0 in WebThreadLock ()
#2  0x33f7865e in -[UITextView dealloc] ()
#3  0x0005d2ce in -[GCPlaceholderTextView dealloc] …
Run Code Online (Sandbox Code Playgroud)

memory-management objective-c grand-central-dispatch ios automatic-ref-counting

10
推荐指数
1
解决办法
7971
查看次数

背景线程上的dealloc

从后台线程调用dealloca 是错误的UIViewController吗?似乎UITextView(可以?)最终调用_WebTryThreadLock哪个导致:

bool _WebTryThreadLock(bool):试图从主线程或Web线程以外的线程获取Web锁.这可能是从辅助线程调用UIKit的结果.

背景:我有一个子类NSOperation,它接受一个selector和一个target对象通知.

-(id)initWithTarget:(id)target {
   if (self = [super init]) {
      _target = [target retain];
   }
   return self;
}

-(void)dealloc {
   [_target release];
   [super dealloc];
}
Run Code Online (Sandbox Code Playgroud)

如果在UIViewController开始NSOperation运行时已经被解雇,那么调用将在后台线程上release触发它dealloc.

iphone memory-management objective-c

5
推荐指数
2
解决办法
4632
查看次数