Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

__bridge not needed for method arguments?

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?

like image 653
Terry Chang Avatar asked Jan 26 '14 09:01

Terry Chang


1 Answers

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.

like image 118
Rob Napier Avatar answered Sep 20 '22 17:09

Rob Napier