As we know, with ARC we need a __bridge
to convert an id to a void *
:
void *t = (void *)self; // ERROR: Cast of ... requires a bridged cast
void *t = (__bridge void *)self; // CORRECT
So are C function calls:
void f(void *t) {
....
}
f((void *)self); // ERROR
f((__bridge void *)self); // CORRECT
I think this should hold for methods as well, and indeed this Beginning ARC in iOS 5 Tutorial gives the following example, and says that the __bridge
is needed:
MyClass *myObject = [[MyClass alloc] init];
[UIView beginAnimations:nil context:(__bridge void *)myObject];
However, today I accidentally dropped a __bridge
in a method call in one of my programs, and the code compiled and ran without any issue. The __bridge
in the above sample seems to be unnecessary:
[UIView beginAnimations:nil context:(void *)myObject]; // COMPILED OK
Is this right? Is the __bridge
really unnecessary in this case? Or removing it changes what the code means?
This is covered in the ARC docs section 3.3.3 (emphasis mine):
3.3.3 Conversion from retainable object pointer type in certain contexts
[beginning Apple 4.0, LLVM 3.1]
If an expression of retainable object pointer type is explicitly cast to a C retainable pointer type, the program is ill-formed as discussed above unless the result is immediately used:
- to initialize a parameter in an Objective-C message send where the parameter is not marked with the cf_consumed attribute, or to
- initialize a parameter in a direct call to an audited function where the parameter is not marked with the cf_consumed attribute.
In your code, myObject
is a "retainable object pointer." A "C retainable pointer type" include void*
(this is a slightly sloppy definition that they're using as a placeholder because Core Foundation "objects" are often void*
).
So an ObjC object can be implicitly converted to a void*
if used as a method parameter. In that case, there are no additional memory management semantics (i.e. it is the equivalent of a __bridge
cast). Section 7.8 warns us that void*
may not be treated this way in the future, but I wouldn't worry about that. If it happens, adding the __bridge
will be trivial.
The one thing to keep in mind is that myObject
is not protected here. It is up to you to make sure it is retained some other way until the animations complete, or you may crash.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With