4

我收到一个未提交的 CATransaction 警告,我无法缝合解决。我的应用程序运行良好,它正在做我期望的每件事,屏幕会尽快更新标签,一切看起来都很好。

    Dec 10 10:40:10 my-iPhone myAppName[5967] <Warning>: CoreAnimation: warning, deleted thread with uncommitted CATransaction; set CA_DEBUG_TRANSACTIONS=1 in environment to log backtraces.

我设置 CA_DEBUG_TRANSACTIONS=1 并找到以下清单。

    Dec 10 10:43:45 my-iPhone myAppName[5994] <Warning>: CoreAnimation: warning, deleted thread with uncommitted CATransaction; created by:
    0   QuartzCore                          0x348fc65d <redacted> + 220
    1   QuartzCore                          0x348fc541 <redacted> + 224
    2   QuartzCore                          0x348fc325 <redacted> + 24
    3   QuartzCore                          0x34900489 <redacted> + 44
    4   QuartzCore                          0x34905091 <redacted> + 456
    5   QuartzCore                          0x34904ebf <redacted> + 42
    6   QuartzCore                          0x34904e91 <redacted> + 44
    7   myAppName                       0x000d9ec1 -[MainViewController updateProgress:] + 56
    8   Foundation                          0x3a75067d <redacted> + 972
    9   libsystem_c.dylib                   0x397d6311 <redacted> + 308
    10  libsystem_c.dylib                   0x397d61d8 thread_start + 8

导致此警告的代码如下所示:

   - (void)updateProgress:(NSString*) myLabelString
    {
    //this is updating a UILabel on the main view
    [myLabel setText:myLabelString];

    }

它是从我调用 performSelectorinBackground 的 for 循环中调用的:

for (;;) {
   // Do stuff here to set up the info for the string

    [self performSelectorInBackground:@selector(updateProgress:) withObject:myLabelString];
    usleep(100000);
    if (stopLoop == YES) {
    // do stuff before we exit for loop            
        break;
    }

}

我已经尝试了几件事,主要是为了确保在退出选择器 "updateProgress" 之前完成对 myLable 的更新,唯一的效果是将时间 (+56) 更改为更大的数字。我也尝试过使用:

    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:1.0f];    
    // edit UILabel here    
    [UIView commitAnimations];

我在另一篇文章中尝试过这个,但由于我没有使用核心动画,编译器反对“CATransaction”作为未声明的标识符,我并不感到惊讶。

      [CATransaction begin];
      [CATransaction setDisableActions:YES];
      //
      [CATransaction commit];

关于如何确定标签更新是否完成的任何建议?正如我所说的应用程序正在运行,我只需要清除此警告。

4

2 回答 2

3

这个问题在开发者论坛上得到了回答。原来我在后台线程上做 UIKit 工作。

我改变了这一行:

    [self performSelectorInBackground:@selector(updateProgress:) withObject:myLabelString];

到:

    [self performSelectorOnMainThread:@selector(updateProgress:) withObject:myLabelString waitUntilDone:NO];

我也尝试将 WaitUntilDone 设置为 YES,这也有效。

于 2012-12-12T04:35:10.937 回答
1

正如 Stephen 所描述的,另一种确保 UI 绘制发生在主线程上的方法是使用该函数dispatch_async()

// Perform all drawing/UI updates on the main thread.
dispatch_async(dispatch_get_main_queue(), ^{
    // Perform any drawing/UI updates here.
});

有关区别的相关帖子dispatch_async()performSelectorOnMainThread:withObjects:waitUntilDone:请参阅主队列上的 performSelectorOnMainThread 和 dispatch_async 之间的区别是什么?

于 2013-11-05T00:52:21.290 回答