I am having issues with the following warning:
CoreAnimation: warning, deleted thread with uncommitted CATransaction; set CA_DEBUG_TRANSACTIONS=1 in environment to log backtraces.
I am using an NSOperation object to perform some calculations, once complete it sends a message back to the AppDelegate that then hides a progress bar and unhides some buttons. If I comment out the message back to the AppDelegate the warning goes away but the progress bar obviously remains visible and animated.
I am using xCode 4.4.1 and OSX 10.8.1, however, when I compile and run the code using the same version of xCode on OSX 10.7.4 I do not get the warning and the code runs as expected.
Setting the CA_DEBUG_TRANSACTIONS=1 environment variable shows the backtrace as coming from an NSControl setEnabled message in the AppDelegate.
The answer is probably staring me in the face but maybe I've had too much coffee!
Your suspicions are right. If NSOperation completes before CoreAnimation is done performing, then you get a nice warning:
*CoreAnimation: warning, deleted thread with uncommitted CATransaction; set CA_DEBUG_TRANSACTIONS=1 in environment to log backtraces.*
This can also happen under some circumstances when a block that is dispatched on a queue triggers some work from CoreAnimation and returns before the CoreAnimation finishes.
The solution I use is simple: On a block or NSOperation that requests work from CoreAnimation, I check that the work has indeed been completed before exiting.
To give you a proof-of-concept example, this is a block to be dispatched on a dispatch queue. In order to avoid the warning, we check that the CoreAnimation is done before exiting.
^{
// 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);
}
}