ARC를 사용할 때 dealloc에서 속성을 nil로 설정합니까?


125

iOS 5에서 자동 참조 계산을 배우려고합니다.이 질문의 첫 부분은 쉽습니다.

  1. 그것이 내가 않는 것이 정확 하지 ARC를 사용하는 경우 내의 dealloc에서 명시 적으로 해제 재산권 문을 작성해야합니까? 즉, 다음은 않는 것이 사실이다 NOT 명시적인 할당 해제를해야합니까?

    @interface MyClass : NSObject
    @property (strong, nonatomic) NSObject* myProperty;
    @end
    
    @implementation MyClass
    @synthesize myProperty;
    @end
  2. 다음으로 중요한 질문은 ARC 릴리스 노트 로의 전환 문서의 내용입니다.

    인스턴스 변수를 해제 할 필요는 없지만 (실제로는 불가능) 시스템 클래스 및 ARC를 사용하여 컴파일되지 않은 다른 코드에서 [self setDelegate : nil]을 호출해야 할 수도 있습니다.

    이것은 ARC로 컴파일되지 않은 시스템 클래스를 어떻게 알 수 있습니까? 언제 나만의 dealloc을 작성하고 명시 적으로 보유 속성을 nil로 설정해야합니까? 속성에 사용 된 모든 NS 및 UI 프레임 워크 클래스에 명시 적 할당 해제가 필요하다고 가정해야합니까?

SO 및 다른 곳에는 수동 참조 추적을 사용할 때 자산의 백업 ivar을 해제하는 관행에 대한 풍부한 정보가 있지만 ARC를 사용할 때는 이에 대한 정보가 상대적으로 적습니다.

답변:


197

짧은 대답 : 아니요, deallocARC 에서 속성을 생략 할 필요는 없습니다 .

긴 대답 : dealloc수동 메모리 관리에서도 속성을 생략해서는 안됩니다 .

MRR에서는 ivars를 해제해야합니다 . 속성을 없애는 것은 setter를 호출하는 것을 의미합니다. setter는 호출해서는 안되는 코드를 호출 할 수 있습니다 dealloc(예 : 클래스 또는 하위 클래스가 setter를 재정의하는 경우). 마찬가지로 KVO 알림을 트리거 할 수 있습니다. 대신 ivar을 해제하면 원하지 않는 동작을 피할 수 있습니다.

ARC에서 시스템은 자동으로 ivar을 해제하므로이 작업이 전부라면 구현할 필요조차 없습니다 dealloc. 그러나 특수 처리가 필요한 객체가 아닌 ivar이있는 경우 (예 : 필요한 할당 된 버퍼 free()) 여전히에있는 것들을 처리해야합니다 dealloc.

또한 자신을 객체의 위임으로 설정 한 경우 해당 관계를 설정 해제해야합니다 dealloc(이것은 호출에 관한 비트입니다 [obj setDelegate:nil]). ARC로 컴파일되지 않은 클래스 에서이 작업을 수행하는 것에 대한 메모는 약한 속성에 대한 끄덕임입니다. 클래스가 delegate속성을 명시 적으로 표시 weak하면 약한 속성의 특성으로 인해 클래스가 사라질 것이므로이 작업을 수행하지 않아도됩니다. 그러나 속성이 표시되어 있으면에 속성을 표시 assign하지 않아야합니다 dealloc. 그렇지 않으면 클래스에 매달려 포인터가 남게되며 위임에 메시지를 보내려고하면 충돌이 발생할 수 있습니다. 이는 대리인과 같이 유지되지 않는 관계에만 적용됩니다.


2
말이 되네요! 내가 당신에게 이것을 물어 보자. 내가 가진 일반적인 시나리오 MyController : UIViewController는 UIView를 만들고 소유하고보기의 델리게이트를 자체적으로 설정 하는 클래스가 있다는 것이다. 해당 뷰의 유일한 보유 소유자입니다. 컨트롤러가 할당 해제되면 뷰도 할당 해제됩니다. 그러면 델리게이트 포인터가 매달려 있는지 여부가 중요합니까?
emfurry

4
@ emfurry : 뷰 컨트롤러가 죽을 때까지 뷰 자체가 뷰 계층 구조에 있지 않아야하며 아무것도하지 않아야하지만 가정하지 않는 것이 가장 좋습니다. 뷰가 나중에 비동기 적으로 작업을 예약하고 뷰 자체가 짧은 시간 동안 뷰 컨트롤러보다 오래 지속되는 경우 (예 : 비동기 작업으로 뷰를 일시적으로 유지하기 때문에) 어떻게해야합니까? 안전을 위해 대의원을 제외시키는 것이 가장 좋습니다. 실제로 문제의 관점이 UIWebView인 경우 문서는 명시 적으로 대리인을 제외해야한다고 명시합니다.
Lily Ballard

3
@zeiteisen : 아니요 unsafe_unretained. assign속성과 정확히 동일하며 MRR 하의 대리자 관계에 대한 일반적인 동작이며 이러한 문제를 해결해야합니다.
릴리 발라드

4
MRC와의 할당 해제에서 세터를 사용하지 않는다는 진술에 동의하지 않습니다. Apple은 권장하지 않지만 코드로도 권장합니다. 실제로 setter를 사용하지 않으면 서 새 문제점을 작성할 수 있습니다. 그것에 대해 몇 가지 큰 토론이 있습니다. 중요한 것은 세터를 올바르게 작성하는 것입니다 (널 값을 전달하면 올바르게 작동해야 함). 때로는 할당 취소 순서를 지켜보십시오.
Sulthan

7
@ Sulthan : dealloc에서 setter를 사용할지 여부는 웜의 큰 캔이지만 내 위치는 기본적으로 줄어 듭니다 . dealloc에서 가능한 한 적은 코드 를 호출하려고합니다 . 세터는 서브 클래스에서 오버라이드하거나 KVO 또는 기타 메커니즘을 통해 부작용을 포함하는 경향이 있습니다. 딜 로크의 부작용은 전염병처럼 특히 피해야합니다. dealloc에서 메소드 호출을 제거 할 수 있으면 그렇게해야합니다. dealloc에서 setter를 호출하지 마십시오.
릴리 발라드

2

반대의 대답을하기 위해서 ...

짧은 대답 : 아니요, deallocARC 에서 자동 합성 속성을 생략 할 필요는 없습니다 . 에있는 사람들을 위해 세터를 사용할 필요는 없습니다 init.

긴 대답 : ARC에서도 사용자 지정 합성 속성을 생략 해야합니다dealloc . 에있는 사람들을 위해 세터를 사용해야합니다 init.

요점은 사용자 정의 합성 속성이 무효화와 관련하여 안전하고 대칭 적이어야한다는 것입니다.

타이머를위한 가능한 세터 :

-(void)setTimer:(NSTimer *)timer
{
    if (timer == _timer)
        return;

    [timer retain];
    [_timer invalidate];
    [_timer release];
    _timer = timer;
    [_timer fire];
}

스크롤보기, 테이블보기, 웹보기, 텍스트 필드에 대한 가능한 설정 기 : ...

-(void)setScrollView:(UIScrollView *)scrollView
{
    if (scrollView == _scrollView)
        return;

    [scrollView retain];
    [_scrollView setDelegate:nil];
    [_scrollView release];
    _scrollView = scrollView;
    [_scrollView setDelegate:self];
}

KVO 속성에 대한 가능한 세터 :

-(void)setButton:(UIButton *)button
{
    if (button == _button)
        return;

    [button retain];
    [_button removeObserver:self forKeyPath:@"tintColor"];
    [_button release];
    _button = button;
    [_button addObserver:self forKeyPath:@"tintColor" options:(NSKeyValueObservingOptions)0 context:NULL];
}

그런 다음에 대한 코드를 복제 할 필요가 없습니다 dealloc, didReceiveMemoryWarning, viewDidUnload, ... 그리고 당신의 재산을 안전하게 공개 할 수있다. 의 속성 없음에 대해 걱정 dealloc했다면 설정자를 다시 확인해야 할 때입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.