9

블록 ivar에서 명백한 참조주기가있는 코드가 있습니다. 다음 코드는 참조주기를 발생시키고 할당 해제는 호출되지 않습니다 :ARC에서 ivar 블록의 __block 자체 참조주기

__block MyViewController *blockSelf = self; 

loggedInCallback = ^(BOOL success, NSError *error){ 
    if (success) 
    { 
     double delayInSeconds = 1.0; 
     dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC); 
     dispatch_after(popTime, dispatch_get_main_queue(), ^(void) 
     { 
      [blockSelf.delegate loginDidFinish]; 
     });    
    } 
}; 

그러나, 나는 캡처 블록의 범위 내 위임에 대한 참조를 유지하기 위해 다른 __block 변수를 만들 경우, 참조주기가 사라집니다 :

__block id <MyViewControllerDelegate> blockDelegate = self.delegate; 

loggedInCallback = ^(BOOL success, NSError *error){ 
    if (success) 
    { 
     double delayInSeconds = 1.0; 
     dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC); 
     dispatch_after(popTime, dispatch_get_main_queue(), ^(void) 
     { 
      [blockDelegate loginDidFinish]; 
     });    
    } 
}; 

여기에 무슨 일이 일어나고 있는지 알고 싶습니다.

답변

16

여기 ARC를 사용하여 귀하의 것으로 가정합니다. ARC 이전의 첫 번째 예는 정상적으로 작동합니다. ARC를 사용하면 __block의 의미가 변경되었습니다. __block 선언은 이제 약하게 캡처되지 않고 강하게 캡처됩니다. 첫 번째 샘플에서 __block__weak으로 바꾸면 모두 예상대로 작동합니다.

두 번째 예제가 작동하는 것처럼 위임자에 대한 강력한 참조를 만들고 있지만 위젯에는 개체에 대한 참조가 없습니다. 따라서 아무 사이클 및 모두 행복합니다.

나는 특히 블록 캡처 주위에, ARC 도입 된 변경에 마이크 애쉬의 기사를 읽고 추천 __weakhttp://www.mikeash.com/pyblog/friday-qa-2011-09-30-automatic-reference-counting.html

+0

완벽한, 감사합니다! 내 질문의 제목을 더 구체적으로 업데이트했습니다. –

+1

iOS 4.3을 대상으로하고 있으므로 대신''__unsafe_unretained''를 사용해야합니다. 그러나 작동합니다. 감사합니다! –