ARC and bridged cast

Morrowless picture Morrowless · Aug 12, 2011 · Viewed 84.2k times · Source

With ARC, I can no longer cast CGColorRef to id. I learned that I need to do a bridged cast. According clang docs:

A bridged cast is a C-style cast annotated with one of three keywords:

(__bridge T) op casts the operand to the destination type T. If T is a retainable object pointer type, then op must have a non-retainable pointer type. If T is a non-retainable pointer type, then op must have a retainable object pointer type. Otherwise the cast is ill-formed. There is no transfer of ownership, and ARC inserts no retain operations.

(__bridge_retained T) op casts the operand, which must have retainable object pointer type, to the destination type, which must be a non-retainable pointer type. ARC retains the value, subject to the usual optimizations on local values, and the recipient is responsible for balancing that +1.

(__bridge_transfer T) op casts the operand, which must have non-retainable pointer type, to the destination type, which must be a retainable object pointer type. ARC will release the value at the end of the enclosing full-expression, subject to the usual optimizations on local values.

These casts are required in order to transfer objects in and out of ARC control; see the rationale in the section on conversion of retainable object pointers.

Using a __bridge_retained or __bridge_transfer cast purely to convince ARC to emit an unbalanced retain or release, respectively, is poor form.

In what kind of situations would I use each?

For example, CAGradientLayer has a colors property which accepts an array of CGColorRefs. My guess is that I should use __brige here, but exactly why I should (or should not) is unclear.

Answer

monkeydom picture monkeydom · Aug 31, 2011

I agree that the description is confusing. Since I just grasped them, I'll try to summarize:

  • (__bridge_transfer <NSType>) op or alternatively CFBridgingRelease(op) is used to consume a retain-count of a CFTypeRef while transferring it over to ARC. This could also be represented by id someObj = (__bridge <NSType>) op; CFRelease(op);

  • (__bridge_retained <CFType>) op or alternatively CFBridgingRetain(op) is used to hand an NSObject over to CF-land while giving it a +1 retain count. You should handle a CFTypeRef you create this way the same as you would handle a result of CFStringCreateCopy(). This could also be represented by CFRetain((__bridge CFType)op); CFTypeRef someTypeRef = (__bridge CFType)op;

  • __bridge just casts between pointer-land and Objective-C object-land. If you have no inclination to use the conversions above, use this one.

Maybe this is helpful. Myself, I prefer the CFBridging… macros quite a bit over the plain casts.