核心动画警告已删除具有未提交 CATransaction 的线程



我遇到以下警告的问题:

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

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

我使用的是xCode 4.4.1和OSX

10.8.1,但是,当我在OSX 10.7.4上使用相同版本的xCode编译和运行代码时,我没有收到警告,并且代码按预期运行。

设置 CA_DEBUG_TRANSACTIONS=1 环境变量将显示回溯跟踪来自应用程序委托中的 NSControl setEnabled 消息。

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

为了与标准的Cocoa范式保持一致,这里推荐的解决方案是在主线程上执行核心动画工作,使用GCD可以轻松完成:

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

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

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

你的怀疑是对的。如果 NSOperation 在 CoreAnimation 完成执行之前完成,则会收到一个很好的警告:

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

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

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

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

^{
   // 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);
   }
}

确保任何 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:之间区别的相关文章,请参阅执行选择或主线程和主队列上的dispatch_async有什么区别?

最新更新