2012-09-20 9 views
37

와 스레드를 삭제 나는 다음과 같은 경고에 문제가 있어요 :코어 애니메이션 경고가 커밋되지 않은 CATransaction

코어 애니메이션 : 경고, 커밋되지 않은 CATransaction와 삭제 스레드; CA_DEBUG_TRANSACTIONS = 1을 backtraces 로그 환경에서 설정하십시오.

일부 계산을 수행하기 위해 NSOperation 개체를 사용하고 있는데, 완료되면 AppDelegate로 메시지를 보내고 AppDelegate는 진행률 막대를 숨기고 일부 단추를 숨김 해제합니다. AppDelegate로 메시지를 주석 처리하면 경고가 사라지지만 진행 표시 줄은 분명히 표시되고 애니메이션으로 유지됩니다.

xCode 4.4.1 및 OSX 10.8.1을 사용하고 있지만 OSX 10.7.4에서 xCode의 동일한 버전을 사용하여 코드를 컴파일하고 실행할 때 경고 메시지가 나타나지 않고 코드가 예상대로 실행됩니다.

CA_DEBUG_TRANSACTIONS = 1 환경 변수를 설정하면 백 트레 이스가 AppDelegate의 NSControl setEnabled 메시지에서 오는 것으로 표시됩니다.

대답은 아마도 나를 얼굴로 바라보고 있지만 어쩌면 나는 너무 많은 커피를 먹었을 것입니다!

+3

저는 오늘이 문제로 조금 놀았습니다. UI 요소를 다시 그려서 CoreAnimation이 끝나기 전에 NSOperation이 완료된다는 문제가 의심됩니다. 백 트레이스는 원래 NSOperation에서 호출 된 메서드를 보여줍니다. NSOperation에서 NSOperation을 구현하여 AppDelegate에 계산이 완료되었음을 알리려고했는데, 이것이 NSOperation이 CoreAnimation에 영향을주지 않고 출시 될 수 있음을 의미하지만, 경고는 여전히 발생하지만 이번에는 CoreFoundation입니다. – Milly

+1

두 경우 모두 프로그램이 예상대로 작동하고 OS 10.8.1 또는 10.8.2에서 실행될 때만 경고가 표시됩니다. – Milly

답변

18

당신의 의혹은 옳습니다. CoreAnimation이 수행되기 전에 NSOperation이 완료되면 다음과 같은 좋은 경고 메시지가 나타납니다.

* CoreAnimation : 커밋되지 않은 CATransaction이있는 경고 스레드 삭제됨. 백 플로우 로그 환경에서 CA_DEBUG_TRANSACTIONS = 1로 설정하십시오. *

큐에서 발송되는 블록이 CoreAnimation에서 일부 작업을 트리거하고 CoreAnimation이 완료되기 전에 반환하는 경우가 있습니다.

내가 사용하는 솔루션은 간단합니다. CoreAnimation에서 작업을 요청하는 블록 또는 NSOperation에서 작업을 끝내기 전에 실제로 완료되었는지 확인합니다.

개념 증명 예를 들어 보겠습니다.이 블록은 디스패치 대기열에 발송됩니다. 경고를 피하기 위해 CoreAnimation이 종료되기 전에 완료되었는지 확인합니다. 일반적으로

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

그것의 빈약 한 형태의 객체를 호출 : 표준 코코아 패러다임과 유지에

^{ 

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

} 
+3

이것은 불필요한 리소스를 사용하므로 최적의 솔루션이 아닙니다. 더 나은 솔루션을 보려면 아래를 참조하십시오. 특히, performSelectorOnMainThread : withObject : waitUntilDone : 또는'dispatch_async()'를 사용합니다. – Dalmazio

+0

이것은 잘못된 해결책이며, 모든 애니메이션이 주 스레드로 보내 져야합니다. – PPierson

+3

@PPierson 실제로 애니메이션이 주 스레드로 발송됩니다. 나는 해결책이 무엇인지 잘못 알지 못한다. – Jean

24

, 여기에 권장되는 솔루션은 쉽게 GCD으로 수행, 메인 쓰레드에서 코어 애니메이션 작업을 수행하는 것입니다 문맥에서 그들은 예상하지 않으므로, 좋은 규칙은 입니다. 항상 메시지를 외부 모듈에 전달할 때 주 스레드로 발송하십시오.

코어 위치와 같은 일부 프레임 워크는 기본 스레드가 아닌 다른 컨텍스트에서 호출 될 경우 로그 메시지를 내 보냅니다. 다른 사람들은 여기 Core Animation과 같은 당신의 예와 같은 비밀스러운 메시지를 내보낼 것입니다.

+1

이 시도하고 나를 위해 작동하지 않았다 – rbp

8
Numist 의해 기술 된 바와 같이 모든 UI 드로잉을 보장하는 또 다른 방법은, 메인 쓰레드에 발생

의 차이에 관한 포스트를 들어 대안 방법 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?

+1

간단하고 좋은 해결책 :) –