아크와 브리지 캐스트


166

ARC으로, 나는 더 이상 캐스팅 할 수 없습니다 CGColorRefid. 브리지 캐스트를해야한다는 것을 알게되었습니다. clang 문서 에 따르면 :

브리지 캐스트는 C 스타일 캐스트는 세 가지 키워드 중 하나의 주석을 붙일 수 :

(__bridge T) op피연산자를 대상 유형으로 캐스팅합니다 T. 경우 T 보존 가능한 개체 포인터 유형이 다음 op비 보존 가능한 포인터 타입이 있어야합니다. 경우 T비 보존 가능한 포인터 타입이며, 다음 작전은 보존 가능한 개체 포인터 유형이 있어야합니다. 그렇지 않으면 캐스트가 잘못 형성됩니다. 소유권 이전이 없으며 ARC는 보유 작업을 삽입하지 않습니다.

(__bridge_retained T) op유지할 수있는 객체 포인터 유형을 가져야하는 피연산자를 대상 유형으로 캐스트 할 수없는 대상 유형으로 캐스트합니다. ARC는 로컬 값에 대한 일반적인 최적화에 따라 값을 유지하며 수신자는 +1의 균형을 맞 춥니 다.

(__bridge_transfer T) op유지할 수없는 포인터 유형을 가져야하는 피연산자를 대상 유형으로 캐스트합니다.이 유형은 보유 가능한 객체 포인터 유형이어야합니다. ARC는 로컬 값에 대한 일반적인 최적화에 따라 둘러싸는 전체 표현이 끝나면 값을 해제합니다.

이러한 캐스트는 ARC 제어 안팎으로 오브젝트를 전송하기 위해 필요합니다. 보유 가능한 객체 포인터의 변환에 대한 섹션의 이론적 근거를 참조하십시오.

ARC가 불균형 유지 또는 방출을 각각 방출하도록 설득하기 위해 순수하게 __bridge_retained또는 __bridge_transfer캐스트를 사용하는 것은 좋지 않은 형태입니다.

어떤 상황에서 각각을 사용해야합니까?

예를 들어, CAGradientLayer가지고 colors배열 허용 속성 CGColorRef들. 내 생각에 나는 __brige여기서 사용해야 하지만 정확히 왜 내가 해야하는지 (또는 그렇지 않아야하는지) 불분명합니다.


17
WWDC 2011 세션 323을 아직 보셨습니까? 그것은 내가 여기서 할 수있는 것보다 ARC를 훨씬 잘 설명합니다. 처음부터 끝까지 모든 세부 사항을 다룹니다. 모든 Mac / iOS 개발자를위한 필수 세션입니다.
rbrown


WWDC 세션에 연결하는 것은 쉬운 일이 아닙니다. developer.apple.com/videos/play/wwdc2011/323 – 관련 비트는 23:15
Daniel

답변:


215

설명이 혼란 스럽다는 데 동의합니다. 방금 그들을 잡았으므로 요약하려고합니다.

  • (__bridge_transfer <NSType>) op또는 대안 으로 ARC로 전송 CFBridgingRelease(op)하는 CFTypeRef동안 보유 횟수를 소비하는 데 사용됩니다 . 이것은 또한id someObj = (__bridge <NSType>) op; CFRelease(op);

  • (__bridge_retained <CFType>) op또는 대안 으로 +1 보유 카운트를 제공하면서 CF 랜드 CFBridgingRetain(op)NSObject오버 오버 를 넘겨주는 데 사용됩니다 . CFTypeRef의 결과를 처리 할 때와 동일한 방식으로 생성 한를 처리해야합니다 CFStringCreateCopy(). 이것은 또한CFRetain((__bridge CFType)op); CFTypeRef someTypeRef = (__bridge CFType)op;

  • __bridge포인터 랜드와 Objective-C 오브젝트 랜드 사이에 캐스트됩니다. 위의 변환을 사용할 의향이없는 경우이 변환을 사용하십시오.

아마도 이것이 도움이 될 것입니다. 나 자신 CFBridging…은 평범한 캐스트보다 매크로를 약간 선호합니다 .


__bridge_transfer를 사용할 때 객체 유지 횟수가 1 씩 증가합니까? 그렇지 않으면 CFRelease ()가 호출되는 순간 객체가 사라지고 아무 것도 가리 키지 않는 것 같습니다. 마찬가지로 __bridge_retain을 사용할 때 ARC는 op의 유지 횟수를 1만큼 줄입니까? 그렇지 않으면 객체가 제대로 해제되지 않는 것 같습니다.
Tony

2
ARC 토지에 들어 서면 더 이상 카운트를 유지하지 않고 강력하고 약한 참조에 대해서만 생각합니다.
monkeydom 2012 년

4
그러나 만약 당신이 아크 랜드 만 강하고 약하다면 충분할 것입니다. 그러나 아크와 비호 환경 사이에서 오브젝트를 전환 할 때 여전히 후드 아래의 리 테이 카운트 수에 대해 생각해야합니다
Tony

3
실제로는 아닙니다. ARC 토지에 출입하는 것에 대해 생각해야합니다. 그리고 이것은 자동 릴리스 파악과 매우 유사합니다. (흥미롭게도 충분히 : ARC는 사전에서 개체를 가져 와서 사용하기 전에 제거하는 것과 같은 일반적인 패턴을 수정합니다.)
monkeydom

3
분석기 도구 (shift + command + B)를 사용하면 현재 코드에서 메모리가 누수되는 경우 자연 언어로 알 수 있으므로 이러한 종류의 의심을 해결하는 데 도움이 될 수 있습니다. 만약 그렇다면, 유지 캐스트를 사용하고있는 동안 비 유지 캐스트를 사용해야합니다. 분석기가 해당 코드 라인에 대해 경고하지 않으면 현재 코드를 잘 사용하고있는 것입니다.
Fabio Napodano

55

iOS 문서에서 이해하기 쉬운 다른 설명을 찾았습니다.

  • __bridge 소유권 이전없이 Objective-C와 Core Foundation간에 포인터를 전송합니다.

  • __bridge_retained (CFBridgingRetain)Objective-C 포인터를 Core Foundation 포인터 로 캐스팅하고 소유권을 귀하에게 이전합니다.

    귀하는 CFRelease 또는 관련 기능을 호출하여 객체의 소유권을 포기할 책임이 있습니다 .

  • __bridge_transfer (CFBridgingRelease) 이동 Objective-C 아닌 포인터 를 Objective-C로 이동 로 이동하고 소유권을 ARC로 전송합니다.

    ARC는 객체의 소유권을 포기합니다.

출처 : 무료 브리지 유형


33

후속 조치로,이 특정한 경우 iOS를 사용하는 경우 Apple은 UIColor 및 해당 -CGColor메소드를 사용 하여 CGColorRef를 colorsNSArray 로 리턴하는 것이 좋습니다 . 에서 ARC 릴리스 노트로 전환 섹션에서, 방법 등을 이용하여 지적한다 "컴파일러는 CF 코코아 방법에서 반환 된 개체 처리"-CGColor 하는 핵심 재단 객체가 자동으로 컴파일러에 의해 적절하게 처리됩니다 반환합니다.

따라서 다음과 같은 코드를 사용하는 것이 좋습니다.

CAGradientLayer *gradientLayer = (CAGradientLayer *)[self layer];
gradientLayer.colors = [NSArray arrayWithObjects:(id)[[UIColor darkGrayColor] CGColor],
                                                 (id)[[UIColor lightGrayColor] CGColor], nil];

현재 Apple의 예제 코드에 위에서 언급 한 (id) 캐스트가 누락되어 컴파일러 오류를 피하는 데 여전히 필요합니다.


원하는 경우 일반적으로 모든 객체 대신 첫 번째 객체를 (id)로 캐스팅하여 벗어날 수 있습니다.
Philippe Sabourin

1
이 질문은 붙여 넣은 코드가 합법적이지 않은 ARC로 캐스팅하는 것에 대해 묻습니다.
Joey Hagedorn

11
@JoeyHagedorn-아마도 당신은 내 대답의 첫 문장에서 ARC 문서에 대한 나의 언급을 놓쳤을 수도 있지만, 이것이 ARC에서 유효 할뿐만 아니라 이러한 UIColor 변환기 메소드에서 NSArrays에 CGColorRef 참조를 제공하기 위해 권장되는 접근법입니다. 저와 다른 많은 사람들은 ARC 가능 응용 프로그램 내에서이 정확한 코드를 사용합니다. Core Foundation 객체를 반환하는 메서드에서 즉시 (id)로 캐스팅하면 해당 객체가 ARC에 자동으로 브리지됩니다.
Brad Larson
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.