사용자 지정 할당 해제 및 ARC (Objective-C)


208

작은 iPad 앱에는 관찰자를 사용하는 "스위치 언어"기능이 있습니다. 모든보기 컨트롤러는 내 관찰자에게 자신을 등록합니다 viewDidLoad:.

- (void)viewDidLoad
{
    [super viewDidLoad];
    [observer registerObject:self];
}

사용자가 "언어 변경"버튼을 누르면 새 언어가 내 모델에 저장되고 관찰자에게 통지되고 updateUi:등록 된 객체 에서 선택기를 호출 합니다.

이것은 TabBarController에 뷰 컨트롤러가있는 경우를 제외하고는 매우 잘 작동합니다. 이는 탭 막대가로드 될 때 뷰를 초기화하지 않고 자식 컨트롤러에서 탭 아이콘을 가져 오기 때문에 viewDidLoad:호출되지 않으므로 뷰 컨트롤러가 언어 변경 알림을받지 않기 때문입니다. 이로 인해 registerObject:호출을 init메서드 로 옮겼습니다 .

viewDidLoad:관찰자로 등록 할 때 다시 등록 viewDidUnload:을 취소했습니다. 내가 지금 등록하고 있기 때문에 init에 등록을 취소하는 것이 좋습니다 dealloc.

그러나 여기 내 문제가 있습니다. 내가 쓸 때 :

- (void) dealloc
{
    [observer unregisterObject:self];
    [super dealloc];
}

이 오류가 발생합니다.

ARC는 'dealloc'의 명시적인 메시지 전송을 금지합니다.

[super dealloc]수퍼 클래스가 올바르게 정리되도록 호출해야 하지만 ARC는이를 금지하므로 이제 막혔습니다. 물건이 죽을 때 알림을받는 다른 방법이 있습니까?


참고로-이와 같은 상황은 메모리 누수를 일으킬 수 있으며 누출 도구에는 표시되지 않습니다. dataModel이 옵저버에 대한 참조를 유지하는 경우 (ivar의 경우에도 ARC에서 기본 사항 임) 유지 횟수가 0보다 크므로 dealloc이 호출되지 않습니다. 따라서 처음에 dealloc을 호출 할 수 있도록 옵저버를 수동으로 등록 취소해야 할 수도 있습니다.
Błażej Czapp

오른 손잡이와 왼손잡이 옵션에 비슷한 것을 구현했습니다. 메시지가 필요한 유일한 VC는 현재 표시된 것입니다. 다른 사람들은 viewDidLoad 또는 viewDidAppear에서 모델을보고 인터페이스를 변경합니다. 아마도 이와 같은 것이 더 잘 작동 할 것입니다.
더그 왓킨스

@BlazejCzapp는 UITabBarController를 사용하고 있기 때문에 UITabBarController가 항상 등록 된 컨트롤러에 대한 참조를 보유한다고 가정합니다 ( '자식'컨트롤러의 경우와 같이) 메모리 누수가 여전히 문제가됩니까? 등록 된 컨트롤러가 언제 할당되는지 알 수 없습니다. 감사합니다
Objectif

답변:


419

ARC를 사용할 때는 [super dealloc]명시 적으로 호출하지 않아도 됩니다 ( Clang LLVM ARC 문서, 7.1.2 장에 설명 된대로 컴파일러가이를 대신하여 처리합니다 ).

- (void) dealloc
{
    [observer unregisterObject:self];
    // [super dealloc]; //(provided by the compiler)
}

4
뷰가 관찰자에 대한 참조를 보유하고 옵저버가 뷰에 대한 참조를 보유하면 원형 참조가 있습니다. 따라서 뷰의 참조 카운트가 0보다 크고 dealloc호출되지 않습니다. [observer unregisterObject:self]dealloc 에 전화하는 것이 합리적 입니까? 내가 무엇을 놓치고 있습니까?
user443854

그것은 일을 원한다. 관찰자 자체가 컨트롤러에 대한 참조를 보유하게합니다. 처음부터 호출이 해제되는 것을 막을 수 있습니다
hasan
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.