All is fine and well with ARC in Objective-C land. However, as soon as you also work with C or C++ code — such as the Chipmunk or Box2D libraries, or the Core Foundation framework — you may find yourself facing compiler errors.
Fortunately, it's half as bad if you understand why the compiler keeps bugging you.
Most errors when working with C/C++ code has to do with the fact that you can't freely cast id to void* and vice versa. For example, the below example won't work:
You'll get an error like this one:
error: cannot initialize a variable of type '...' with an lvalue of type '...'
The types in the error message mentioned may differ but you'll see a __strong keyword thrown in for good measure. Well, you might think this can be fixed by properly casting to the correct types:
This time the error is different, each of the two casts above generates a different message:
1: Cast of Objective-C pointer type 'NSObject *' to C pointer type 'void *' requires a bridged cast
2: Cast of C pointer type 'void *' to Objective-C pointer type 'NSObject *' requires a bridged cast
ARC adds the keywords __bridge, __bridge_transfer and __bridge_retained which must be used when casting. Here's the above example with a "bridged cast" that fixes the compile errors:
The use of __bridge in the cast tells the compiler that the object's lifetime doesn't change, and that you understand that if the object's memory is released it may result in a dangling pointer and a potential crash. This is the same behavior to non-ARC code, but ARC really wants to make sure you understand the implications and potential dangers. In ARC terms, you specify that the cast creates a "unsafe unretained" reference.
When interfacing with Core Foundation you may want to use __bridge_retain to tell ARC to take on ownership of the object (retain it). Likewise, __bridge_transfer tells ARC to release the object after the expression.