CoreAnimation警告已删除的线程与未提交的CATransaction

时间:2012-09-20 06:35:46

标签: multithreading core-animation nsoperation catransaction

我遇到以下警告问题:

CoreAnimation:警告,删除线程与未提交的CATransaction;在环境中设置CA_DEBUG_TRANSACTIONS = 1以记录回溯。

我正在使用NSOperation对象来执行一些计算,一旦完成,它会将消息发送回AppDelegate,然后隐藏进度条并取消隐藏某些按钮。如果我将消息注释回AppDelegate,则警告消失,但进度条显然仍然可见并且已设置动画。

我正在使用xCode 4.4.1和OSX 10.8.1,但是,当我在OSX 10.7.4上使用相同版本的xCode编译和运行代码时,我没有得到警告,代码按预期运行。< / p>

设置CA_DEBUG_TRANSACTIONS = 1环境变量会将回溯显示为来自AppDelegate中的NSControl setEnabled消息。

答案可能是盯着我,但也许我喝的咖啡太多了!

3 个答案:

答案 0 :(得分:24)

为了与标准的Cocoa范例保持一致,这里推荐的解决方案是在主线程上执行Core Animation工作,使用GCD轻松完成:

dispatch_async(dispatch_get_main_queue(), ^{
    [self.delegate redrawSomething];
});

一般来说,在他们不期望的上下文中调用对象的形式很差,所以一个好的经验法则是在向外部模块传递消息时总是调度到主线程上。

某些框架(如Core Location-with)如果从主线程以外的任何上下文调用它们,则会发出日志消息。其他人会发出神秘的消息,例如你的核心动画示例。

答案 1 :(得分:19)

你的怀疑是正确的。 如果在完成CoreAnimation执行之前NSOperation完成,那么你会得到一个很好的警告:

* CoreAnimation:警告,删除线程与未提交的CATransaction;在环境中设置CA_DEBUG_TRANSACTIONS = 1以记录回溯。*

在某些情况下,当在队列上调度的块触发CoreAnimation中的某些工作并在CoreAnimation完成之前返回时,也会发生这种情况。

我使用的解决方案很简单:在从CoreAnimation请求工作的块或NSOperation上,我在退出之前检查工作是否确实已完成。

为了给出一个概念验证示例,这是一个要在调度队列上调度的块。为了避免警告,我们在退出之前检查CoreAnimation是否已完成。

^{

   // 1. Creating a completion indicator

   BOOL __block animationHasCompleted = NO;

   // 2. Requesting core animation do do some work. Using animator for instance.

   [NSAnimationContext runAnimationGroup:^(NSAnimationContext *context){
      [[object animator] perform-a-nice-animation];
   } completionHandler:^{
      animationHasCompleted = YES;
   }];

   // 3. Doing other stuff…

   …

   // 4. Waiting for core animation to complete before exiting

   while (animationHasCompleted == NO)
   {
       usleep(10000);
   }

}

答案 2 :(得分:8)

确保在主线程上进行任何UI绘制的另一种方法,如Numist所描述,使用方法performSelectorOnMainThread:withObject:waitUntilDone:performSelectorOnMainThread:withObject:waitUntilDone:modes:

- (void) someMethod
{
    [...]

    // Perform all drawing/UI updates on the main thread.
    [self performSelectorOnMainThread:@selector(myCustomDrawing:)
                           withObject:myCustomData
                        waitUntilDone:YES];

    [...]
}

- (void) myCustomDrawing:(id)myCustomData
{
    // Perform any drawing/UI updates here.
}


有关dispatch_async()performSelectorOnMainThread:withObjects:waitUntilDone:之间差异的相关帖子,请参阅Whats the difference between performSelectorOnMainThread and dispatch_async on main queue?