2012-01-13 1 views
0

이것은 내 패턴입니다.대리인에게 인스턴스가 더 이상 필요하지 않음을 올바르게 알리는 방법은 무엇입니까?

1) SpecialView는 MessageView를 만들고 강력한 참조를 보유합니다.

2) 사용자가 MessageView의 버튼을 탭하여 페이드 아웃시킵니다. 그런 다음 MessageView는 그것이 완전히 사라져 버린 대리자 인 SpecialView를 알립니다.

3) SpecialView가 MessageView를 출시합니다. 내가 다시 바로 MessageView 출시 대리자를 호출하고있어 마지막 줄에서

- (void)fadedOut:(NSString*)animationID finished:(NSNumber*)finished context:(void*)context { 
    [self.delegate messageViewFadedOut:self]; // delegate releases us... 
    // self maybe got deallocated... BOOM! 
    // now what? method of a zombie returns? stack freaks out? 
} // does it even return? 

:

문제는 이것이다. -fadedOut : finished : context : 코어 애니메이션 didStopSelector 콜백에 의해 호출됩니다.

는 나의 두려움은 MessageView 인스턴스가 즉시 -fadedOut 전에 을 해제 할 예정이다 : 완료 : 컨텍스트 : 매우 불쾌한 임의 버그 옛적에 한 번

의 원인이 완전히 돌아 오래된 베테랑 프로그래머는 말했다 나 : "너가 앉아있는 지점을 절대로 잘라내 지마." 유지 - 오토 릴리즈 춤이 허용되지 않습니다, ARC에서,

- (void)fadedOut:(NSString*)animationID finished:(NSNumber*)finished context:(void*)context { 
    //[[self retain] autorelease]; 
    [self.delegate messageViewFadedOut:self]; // delegate releases us... 
} 

그러나 :

그래서 인스턴스가이 메소드가 반환 될 때까지 남아 있는지 확인하기 위해, 나는 대리자를 호출하기 전에 유지-autorlease 댄스를 만든 더 이상 (마이그레이션 도구에서 허용되지 않음) ARC 시스템에 이와 같은 작업을 수행 할 수있는 방법이 없을 것입니다.

그래서 내가 대신이 전략을 내놓았다 :

- (void)fadedOut:(NSString*)animationID finished:(NSNumber*)finished context:(void*)context { 
    [self.delegate performSelector:@selector(messageViewFadedOut:) withObject:self afterDelay:0]; 
} 

이 지연 performSelector 잘하면 방법이 완전히 반환 할 수 있습니다. 내가 아는 한 0의 지연은 셀렉터가 다음 루프 반복에서 즉시 수행되는 것을 보장합니다.

가짜이기도합니다.

다른 개체를 호출 한 메서드가 완전히 반환되기 전에 개체의 할당이 취소 될 가능성이있는 다른 개체에 대한 마지막 참조를 파기하도록 다른 개체에 요청하는이 문제를 올바르게 해결하려면 어떻게해야합니까? 스택 트레이스 좀비 같은 것이있을 수 있습니까?

그리고 ARC에서 어떻게 해결해야합니까?

답변

0

사실, retain-autorelease를 에뮬레이트하려고 시도하는 대신 대표 메시지 메서드 이 호출 될 때까지 메시지보기에 대한 소유 참조가 해제되어 있는지 확인해야합니다. . willFadeOut: 메서드에 대한 계약은 해제되지 않는다고 가정 할 수 있지만 fadedOut: 또는 didFadeOut: 메서드는 할당이 해제 될 개체 여야합니다.

당신의 dealloc 메서드가 이상한 무작위 버그를 피할 수있는 이상적인 해결책은 발생중인 모든 활성 페이드 아웃 애니메이션을 취소하는 것입니다 (어딘가에 대한 참조를 보유).그렇게하면 dealloc에 도달하는 방법이나시기가 마음에 들지 않습니다. 왜냐하면 dealloc은 X를 수행하여 개체 상태가 사라지거나 시각적으로 이상이 생기는 것을 방지하기 때문입니다.

그래서 당신의 솔루션 (performSelector:withObject:afterDelay:) 또는 어쩌면 GCD 블록을 사용 : 게다가

- (void)fadedOut:(NSString*)animationID finished:(NSNumber*)finished context:(void*)context 
{ 
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 250 * NSEC_PER_MSEC), // 250ms 
        dispatch_get_current_queue(), 
        ^{ 
         [self.delegate messageViewFadedOut:self]; 
        }); 
} 

, ARC 그냥 autorelease 즉시, 왜 당신이 그 코드 섹션을 여러 번 무리를 테스트하고 무슨 일이 표시되지 않습니다 수 ? dealloc에 중단 점을 넣고 메서드가 반환되기 전에 중단 점이 있는지 확인합니다.

+0

동의! 그러나 실제 질문은 : 객체 중 하나가 완전히 반환 된 메서드가 있기 전에 객체의 할당을 해제하면 위험 할 수 있습니까? 위의 코드에서 볼 수 있듯이 대리자를 호출 한 후에는 아무 것도 발생하지 않습니다. 그래서 이론적으로 아무런 문제가 없습니다. 런타임을 제외하고 좀비가 돌아오고 있다는 사실에 대해 괴롭힘. – openfrog

+0

오. 아니요, 제가 말할 수있는 한 위험하지 않습니다. 나는 그것을 프로덕션 애플 리케이션에서 직접하고 어떤 부작용도 발생하지 않았다. 나는 방법의 마지막 라인에서만 그것을 할 것이다. 그렇지 않으면'dealloc''d'self에 접근하려고 시도 할 수있는 것이있을 수있다. – darvids0n