__weak 참조와 __block 참조의 차이점은 무엇입니까?


80

저는 Xcode의 문서를 읽고 있는데 여기에 저를 당혹스럽게하는 것이 있습니다.

__block typeof(self) tmpSelf = self;
[self methodThatTakesABlock:^ {
    [tmpSelf doSomething];
}];

다음은 문서에서 복사되었습니다.

블록은 캡처하는 변수에 대한 강력한 참조를 형성합니다. 당신이 사용하는 경우 self블록 내에서 블록에 강한 참조를 형성 self그렇다면, self또한 블록에 대한 강한 참조 (가 일반적으로 수행하는), 강한 참조주기 결과가 있습니다. 순환을 피하려면 __block위의 예에서와 같이 블록 외부에서 self에 대한 약한 (또는 ) 참조를 만들어야합니다 .

'약한 (또는 __block)'이 무슨 뜻 인지 이해가 안 되나요?

이다

__block typeof(self) tmpSelf = self;

__weak typeof(self) tmpSelf = self;

여기도 똑같나요?

문서에서 다른 부분을 찾았습니다.

참고 : 가비지 수집 환경에서 __weak__block수정자를 변수에 모두 적용 하면 블록이 활성 상태를 유지하는지 확인하지 않습니다.

그래서 저는 완전히 당황합니다.

답변:


109

__block에 대한 문서에서

__block 변수는 변수의 어휘 범위와 변수의 어휘 범위 내에서 선언되거나 생성 된 모든 블록 및 블록 복사본간에 공유되는 저장소에 있습니다. 따라서 프레임 내에서 선언 된 블록의 복사본이 프레임의 끝을 넘어서 살아남는 경우 (예 : 나중에 실행하기 위해 어딘가에 대기열에 추가됨) 스토리지는 스택 프레임의 파괴에서 살아남습니다. 주어진 어휘 범위의 여러 블록은 동시에 공유 변수를 사용할 수 있습니다.

__weak에 대한 문서에서

__weak은 참조 된 객체를 활성 상태로 유지하지 않는 참조를 지정합니다. 약한 참조는 객체에 대한 강한 참조가 없을 때 nil로 설정됩니다.

그래서 그들은 기술적으로 다른 것들입니다. __block은 변수가 외부 범위에서 블록 범위로 복사되는 것을 중지하는 것입니다. __weak은 자체 구분 약한 포인터입니다.

기술적으로 말씀 드렸는데, 귀하의 경우에는 (거의) 같은 일을 할 것이기 때문입니다. 유일한 차이점은 ARC를 사용하는지 여부입니다. 프로젝트가 ARC를 사용하고 iOS4.3 이상 전용 인 경우 __weak을 사용하십시오. 전역 범위 참조가 어떻게 든 릴리스 인 경우 참조가 nil로 설정되도록합니다. 프로젝트가 ARC를 사용하지 않거나 이전 OS 버전 용인 경우 __block을 사용합니다.

여기에는 미묘한 차이가 있습니다. 이해했는지 확인하십시오.

편집 : 퍼즐의 또 다른 조각은 __unsafe_unretained입니다. 이 수정자는 __weak과 거의 동일하지만 4.3 이전 런타임 환경에 사용됩니다. 그러나 nil로 설정되어 있지 않고 포인터를 매달아 놓을 수 있습니다.


1
ARC를 사용하는 iOS7에도 계속 적용 되나요? 프로파일 러를 실행했는데 __block 또는 __weak을 사용하지 않고 블록에서 self를 참조하지 않아도 컨트롤러가 해제되는 것을 확인했습니다.
Jay Q.


1
함께 사용하는 것은 어떻습니까? __block _weak NSString *strEg;?
CyberMew

5

수동 참조 카운팅 모드에서 __block id x; x를 유지하지 않는 효과가 있습니다. ARC 모드에서 __block id x; 기본적으로 x를 유지합니다 (다른 모든 값과 마찬가지로). ARC에서 수동 참조 계수 모드 동작을 얻으려면 __unsafe_unretained __block id x;를 사용할 수 있습니다. 그러나 __unsafe_unretained라는 이름에서 알 수 있듯이 유지되지 않는 변수를 갖는 것은 위험하므로 (매달릴 수 있기 때문에) 권장되지 않습니다. 두 가지 더 나은 옵션은 __weak (iOS 4 또는 OS X v10.6을 지원할 필요가없는 경우)을 사용하거나 __block 값을 nil로 설정하여 유지주기를 중단하는 것입니다.

사과 문서



0

self in block을 사용할 때는 self를 유지할 수 있으므로 __block이 아닌 __weak을 사용해야합니다 .

강한 자아가 필요한 경우 다음과 같이 사용할 수 있습니다.

__weak typeof(self) *weakSelf = self;
[self methodThatTakesABlock:^{
    if (weakSelf) {
        __strong typeof(self) *strongSelf = weakSelf;
        [strongSelf doSomething];
    }
}];
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.