2012-01-10 6 views
5

Mike Ash has written this introduction to ARC 그가 어디과 같이 소개 :언제 ARC를 사용하여 __weak으로 로컬 변수를 선언하겠습니까?

__weak Foo *_weakFoo = [object foo]; 

가 왜 로컬, 임시 변수를 위해 그렇게 할 것입니까? __weak은 참조 된 객체의 할당이 해제 되 자마자 _weakFoo 포인터를 자동으로 nil로 설정하는 0 참조입니다. 또한, __weak는 아이폰 OS에서만 사용할 수 있습니다> =

단순히이이 항상 객체 또는 전무를 반환 할 것으로 예상된다

Foo *_weakFoo = [object foo]; 

? : 할 때 문제로 실행됩니다 5. 내 추측은 다음과 같습니다.

Foo *_weakFoo = [object foo]; 
[self doSomethingStupid]; // does something bad so foo gets deallocated 
[_weakFoo doIt]; // CRASH! msg sent to deallocated instance 0x123456 

ARC와 관련된 버그 중 하나는 다음과 같습니다. 내가 더 이상 객체가 필요 없다는 것을 언제 알 수 있습니까? 나는 포인터를 nil 또는 다른 것으로 설정하면 이전에 참조 된 객체가 더 이상이 소유자가 필요하지 않으므로 멀리 갈 수 있다고 생각합니다. 그러나 요점은 : 나는 그것을 0으로 설정했다. 그래도 아무렇지도 않습니다!

로컬 변수에 대한 __weak은 어떨까요? 그리고 내가 정말로 필요로 할 때 어떤 종류의 미친 짓을해야합니까?

답변

9

보유주기를 피하기 위해 블록 내부에서 self을 조작해야한다면 __weak 로컬 변수를 사용합니다. 이 예제에서 GCD와 블록을 사용하여 문자열에 대한 네트워크 요청을 수행 한 다음 클래스에서 선언 한 레이블 (이 경우 TurtlesViewController)에 설정합니다.

__weak TurtlesViewController *weakSelf = self; 
dispatch_queue_t networkQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 

dispatch_async(networkQueue, ^{ 

    // Kick off a network task for some data that is going to populate a label declared on our class 
    NSString *returnString = [networkDataSource retrieveTurtleTime]; 

    // Dispatch back to the main thread to populate the UILabel 
    dispatch_async(dispatch_get_main_queue(), ^{ 

     // Using self.label here creates a retain cycle. Self owns the block and the block has captured self 
     self.label.text = returnString; 

     // Instead, we use weakSelf for our reference to the label as it will be torn down by ARC at the end of the loop. 
     weakSelf.label.text = returnString; 
    }); 
}); 
+1

어떻게주기가 유지 될 수 있습니까? – openfrog

+1

@openfrog -이 특정 블록은 보존주기의 가장 큰 위험이 아닐 수도 있지만, 블록 기반 관찰자 (NSNotificationCenter의 -addObserverForName : object : queue : usingBlock :'). 객체에 그러한 옵저버를 설정하고'self'에있는 어떤 것을 참조한다면, 객체가 블록에 고정되어 있고 블록이 객체에 고정되어있을 때 사이클을 설정하게됩니다. –

+2

이 글을 작성한 후에 dispatch_async()가 블록을 복사하기 때문에 가장 좋은 예제는 아니라는 사실을 깨달았습니다. 더 나은 예제는 NSBlockOperation을 사용했을 것입니다. 인스턴스의 인스턴스가 객체의 수명 동안 전달 된 블록을 소유하고 있기 때문에 유지 사이클을 더 쉽게 할 수 있습니다. –

관련 문제