2013-02-17 3 views
1

AppDelegate은 활성 창 컨트롤러 목록을 유지 관리하므로 ARC가 너무 빨리 할당 취소하지 않습니다. 알림 스레드에서 취급을하는 것은 그것이 준비하기 전에 컨트롤러를 할당 해제 위험 때문에 애니메이션이 발생했을 때 창 할당 취소

- (void) windowWillClose: (NSNotification*) notification { 
    [self performSelectorOnMainThread: @selector(removeWindowControllerInMainThread:) 
     withObject: windowController 
     waitUntilDone: NO]; 
} 

- (void) removeWindowControllerInMainThread: (id) windowController { 
    [windowControllers removeObject: windowController]; 
} 

내가 메인 스레드를 사용 : 그래서 나는이 같은 알림 핸들러를 가지고있다.

이제는이 방법이 효과적입니다. 현재 애니메이터가 실행중인 경우는 예외입니다. 나는 어떤 곳에서 애니메이터를 사용하며, NSAnimationContext을 통해. 나는 this QA을 보았고 대답은 받아 들일 수 없다. 잠시 기다리십시오. 애니메이션을 완성하기 만하면 정말 외설적이며 일하는 것이 보장되지 않습니다. 참으로 그렇지 않습니다. 나는 현재의 애니메이션 지속 시간보다 더 큰 지연을 가지고도 performSelector:withObject:afterDelay을 사용해 보았고 애니메이터가 여전히 nil 오브젝트에 대해 실행되도록합니다.

이렇게 컨트롤러 정리를 수행하는 가장 좋은 방법은 무엇입니까? NSAnimationContext을 사용하지 말고 대신 방법을 사용하는 NSAnimation을 사용 하시겠습니까?

답변

2

첫 번째로, 일부 애니메이션이 무기한으로 실행되거나 아주 오랫동안 실행되는 경우,이를 막을 수있는 방법이 있어야합니다.

하지만보기에서 암시 적 애니메이션과 같은 경우에는 완료 방법을 사용하면됩니다.

self.animating=YES; 
    [NSAnimationContext runAnimationGroup:^(NSAnimationContext *context){ 
    [[v animator] setAlphaValue: 1]; 
} completionHandler:^{ 
    self.animating=NO; 
}]; 

이제 애니메이션이 실행 중인지 여부를 폴링하고 실행 중이 아닌 경우 계속 진행하여 창을 닫습니다.

폴링을 수행하는 좋은 방법 중 하나는 고정 지연 타이머를 설정하는 것입니다. 애니메이션이 아직 실행 중이면 타이머를 재설정하고 다른 간격을 기다리십시오.

또는 완성 처리기에서 알림을 보낼 수 있습니다.

+0

나는 폴링에 대한 생각이 싫지만 괜찮습니다. DRY와 관심의 분리는 이것이 창 컨트롤러가 전혀 신경 쓸 필요가없는 것이어야한다는 것을 나타냅니다. 그래서이 기능을 창 컨트롤러 기본 클래스에 패키징했습니다. –

+0

폴링하지 않으려면 완료 핸들러에서 컨트롤러에 알림을 보냅니다. 또는 애니메이션 객체가 windowController에 대해 알고 있으면 애니메이션이 시작될 때'willAnimate' 메시지를 보내고 애니메이션이 끝날 때'didAnimate' 메시지를 보냅니다. –

2

저는 NSAnimationContext을 사용하지 않았습니다 (주로 NSAnimation으로 이것을했으나 대부분 역사적인 이유로 사용했습니다). 그러나 내가 이와 비슷한 것을 관리하는 것과 같은 전형적인 방법은 수명이 짧은 보유 루프를 만드는 것입니다.

마크의 대답은 정확히 올바른 아이디어이지만 폴링은 필요하지 않습니다. 완료 핸들러에서 self을 참조한다는 사실은 self이 완료 핸들러를 실행하기 전에 할당 해제 할 수 없음을 의미합니다. animating을 읽었는지 여부는 실제로 중요하지 않습니다. ARC는 블록이 사용자를 참조하기 때문에 완료 블록이 실행될 때까지 계속 주위를 지켜야합니다.

또 다른 유사한 기술은 objc_setAssociatedObject을 사용하여 애니메이션 컨텍스트에 자신을 첨부하는 것입니다. 완료 블록이 실행될 때까지 유지됩니다. 완료 블록에서 연결된 개체로 self을 제거하면 자유롭게 할당을 취소 할 수 있습니다. 이 접근법에 대한 좋은 점은 animating과 같은 가짜 추가 속성을 필요로하지 않는다는 것입니다.

물론 때로는 마지막으로 절박한 조치는 단명 된 자기 참조를 만드는 것입니다. 예 :

- (void)setImmortal:(BOOL)imortal { 
    if (immortal) { 
    _immortalReference = self; 
    } 
    else { 
    _immortalReference = nil; 
    } 
} 

저는이 마지막 옵션을지지하지 않습니다. 그러나 그것이 존재한다는 것을 알고, 더 중요한 것은 왜 그것이 작동 하는지를 아는 것이 좋다.