CoreAnimation warning deleted thread with uncommitted CATransaction

前端 未结 3 751
深忆病人
深忆病人 2020-12-24 07:04

I am having issues with the following warning:

CoreAnimation: warning, deleted thread with uncommitted CATransaction; set CA_DEBUG_TRANSACTIONS=1 in environment to l

相关标签:
3条回答
  • 2020-12-24 07:15

    In keeping with standard Cocoa paradigms, the recommended solution here is to perform your Core Animation work on the main thread, easily done with GCD:

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

    In general it's poor form to call objects in contexts they don't expect, so a good rule of thumb is to always dispatch onto the main thread when delivering messages to external modules.

    Some frameworks—like Core Location—with emit a log message if they are called from any context other than the main thread. Others will emit cryptic messages, such as your example here with Core Animation.

    0 讨论(0)
  • 2020-12-24 07:25

    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);
       }
    
    }
    
    0 讨论(0)
  • 2020-12-24 07:26

    Another way of ensuring any UI drawing occurs on the main thread, as described by Numist, is using the method performSelectorOnMainThread:withObject:waitUntilDone: or alternatively 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.
    }
    


    For a related post on the difference between dispatch_async() and performSelectorOnMainThread:withObjects:waitUntilDone: see Whats the difference between performSelectorOnMainThread and dispatch_async on main queue?

    0 讨论(0)
提交回复
热议问题