1

나는 ARC를 사용하여 응용 프로그램을 작성 중이며 다음과 같은 문제가 발생하는지 궁금합니다. 특히, 나는 'A'라는 객체를 만들고, GCD를 사용하여 코드 블록을 주 스레드의 큐에 추가하고 코드 블록에서 객체에 대한 약한 참조에 대해 몇 가지 연산을 수행합니다. 그러나 코드 블록이 실행될 때까지는 객체가 이미 무효화되었습니다. 코드 블록에는 객체에 대한 약한 참조 만 있기 때문에 문제가 발생합니까? 아니면 컴파일러는 어떻게 든 내 코드 블록이 실행될 때 필요하기 때문에 객체에 대한 참조를 유지해야한다는 것을 알고 있습니까?그랜드 센트럴 디스패치 코드 블록

Foo *A = [[Foo alloc] init]; 

    __weak Foo *weakA = A; 

    dispatch_async(dispatch_get_main_queue(), ^{ 

      //...do something here with weakA 
    }); 

    A = nil; 

고마워요!

+0

내가 말할 것입니다. 빌드하고 실행하십시오!여기서 대답을 기다리는 대신 시도해보십시오. 새 프로젝트를 만들고 그 부분 만하십시오. – Novarg

+0

'Foo' 앞에'__block'을 추가하십시오. –

답변

2

이것은 약간의 미묘한 점을 가지고 흥미로운 질문입니다.

컴파일러에서 __weak으로 태그를 지정하여 블록 내에서 참조를 무시하도록 명시 적으로 지정 했으므로이 코드는 블록이 실행될 때까지 개체를 활성 상태로 유지하는 데 충분하지 않습니다. 그것은 당신이 이미 그것에 대해 분명하게 들리는 것처럼 들립니다.

일반적으로 weakA와 같은 약한 참조는 참조하는 객체가 할당 해제 될 때 무효화됩니다. 그러나 weakA는 스택 변수이므로 블록에서 참조 될 때 블록은 블록이 생성 될 때 그 값을 추측하는 const-ified 버전을받습니다. 아마도 weakA의이 const 사본은 무효화 될 수 없습니다. 자세한 내용은 this section of the Apple docs을 참조하십시오. 당신이 다음

__block __weak Foo *weakA = A; 

에 weakA의 선언을 변경하는 경우

는 weakA 스택을 승진의 원본 문장에서와 블록에서 모두 쓸 수있다. 참조 된 객체를 자체적으로 활성 상태로 유지하지는 않지만 블록 실행 시점에서 해당 값이 nil인지 여부를 확인할 수 있습니다. __block에

자세한 내용은 here를 찾을 수있다 -는 'ARC는 새로운 평생 예선 "아래로 건너 뜁니다.

3

여기에 __weak을 사용하고 계십니까? 위의 코드에서

Foo *a = [[Foo alloc] init]; 

dispatch_async(dispatch_get_main_queue(), ^{ 
    [a something];  
}); 

, 블록을 : 당신이 블록을 원하는 경우에, 당신은 아무것도 할 필요가 없습니다 "이후 개체에 대한 참조를 유지 [당신] 코드 블록이 실행될 때 그것을 필요" a을 유지하므로 블록이 실행될 때 존재하게됩니다.

this question에 설명되어있는 것처럼 __weak 블록을 사용해야하는 유일한 시간은 블록 자체를 유지할 때 발생하는 유지주기를 중단하는 것입니다. 예를 들어 : someObject__weak을 선언되지 않은 경우 다음

__weak Foo *someObject = [bar getAFoo]; 

[someObject doSomeTaskWithCompletionHandler:^{ 
    [someObject doSomethingElse]; 
}]; 

는, 당신은 someObject은 아마도 블록을 유지하는 것이기 때문에이 어떤 일을 할 때까지이 블록을 유지해야하기 때문에이 (사이클을 유지할 것 작업), 블록은 someObject을 유지합니다. 여기서 __weak을 사용하면 블록이 someObject을 보유하지 않도록 알려 주므로 오류는 발생하지 않습니다. someObject 블록을 소유하고 있기 때문에 당신은 약 someObject되는 nil 블록이 실행될 때 걱정할 필요가 없습니다. (someObject이 할당 해제되어야하는 경우, 블록은 실행되지 않습니다).

관련 문제