Under manual memory management, I use this pattern fairly often:
NSString * myStr = /* some local object */
[UIView beginAnimation:@"foo" context:(void *)[myStr retain]];
And then, later and asynchronously:
- (void)animationDidStop:(NSString *)anim finished:(NSNumber *)num context:(void *)context
{
NSString * contextStr = (NSString *)context;
// ...
[contextStr release];
}
i.e. I manually managed the lifetime of an object used as an opaque context. (This is true for the old UIView animations but also for other kinds of API that I use.)
Under ARC, my instinct is that I want to __bridge_retained
going in and __bridge_transfer
in the handler, as suggested here. But this treats a Cocoa object as a CFType
not because it's really bridged, but just for the purpose of shoving a retain down its throat.
Is this valid, and is this stylistically acceptable? If not, what's the better* solution?
(The accepted answer in this question gives a different answer, saying that __bridge
alone is OK, but that seems to me to be wrong, since the original string would be at risk of being deallocated as soon as it goes out of scope in the first function. Right?)
*Please don't say "use block-based animations instead". (That's not what I'm asking about.)
Go with your instinct.
__bridge_retained
transfers management of an object to you from ARC, while__bridge_transfer
does the reverse, don't worry about treating the object as aCFType
- you're not really doing that just taking over management.The other approach you see recommended is to construct your code so that ARC retains management, but this can easily come across as contrived (and get messy). Having the API you're using maintain the value as it is designed to do is clean; just comment the code appropriately where management is handed to the API and returned back to ARC.
Even if using
__bridge_retained
/__bridge_transfer
seems fine to me (transferring ownership to CoreFoundation or to any C code or to yourself is quite the same you just tell ARC that you are responsible for the object ownership at some point and give the ownership back to ARC later), you can instead keep astrong
reference on your object you use as yourcontext
somewhere if you prefer, so that ARC does not reclaim its memory.This can be achieved by using a
@property(strong)
in your class for example, affecting it to the value when you previously did yourretain
and assigning it tonil
when you previously did yourrelease
to let the string go.Note that if you need to keep around multiple contexts in the same class, you may opt for the option to use an
NSMutableArray
that keeps your context strings around instead of declaring a property for each context.