I'm trying to convert manual retain release code to ARC.
I'm struggling to figure out the correct way to toll free bridge when I have an Objective-C convenience constructor whose return pointer value is being stored in a CFTypeRef.
Existing code, using MRR:
@interface SourceItemCell UITableViewCell
{
CATextLayer *mSourceText;
}
@implementation SourceItemCell
- (id)init
{
self = [super init];
mSourceText = [CATextLayer layer];
// key line I'm wondering about:
mSourceText.font = [UIFont fontWithName:@"HelveticaNeue" size:12.0];
[[self contentView].layer addSublayer:mSourceText];
return self;
}
To keep you from having to look up the documentation, the font property of CATextLayer is of type CFTypeRef.
It seems like my options are:
mSourceText.font = (__bridge CFTypeRef)[UIFont fontWithName:@"HelveticaNeue" size:12.0];
or:
mSourceText.font = (__bridge_transfer CFTypeRef)[UIFont fontWithName:@"HelveticaNeue" size:12.0];
or:
mSourceText.font = (__bridge_retained CFTypeRef)[UIFont fontWithName:@"HelveticaNeue" size:12.0];
Here's my thinking. The clearest guide to toll free bridging I've found is http://www.mikeash.com/pyblog/friday-qa-2011-09-30-automatic-reference-counting.html . There's a similar example of a cast from an Objective-C type to a C type, about which he writes:
By using __bridge_retained, we can tell ARC to transfer ownership out of the system and into our hands. Since ownership is transferred, we're now responsible for releasing the object when done with it, just like with any other CF code
...otherwise, if we were only to use __bridge, ARC would not make any effort to hold onto the memory on our CFTypeRef's account.
So here is what I think is the most sensible way to go:
mSourceText.font = (__bridge_retained CFTypeRef)[UIFont fontWithName:@"HelveticaNeue" size:12.0];
... // At some later point
CFRelease(mSourceText.font);
Now, if that's correct, I'm still pretty unclear on when I could be sure it's safe to release, but if I never released, it would at least be just a small memory leak, right?
In conclusion, my actual questions are:
- Is my proposed code correct?
- Where should I CFRelease this object? In the dealloc function for SourceItemCell?
Here's why I didn't think related questions answered my question:
- Must I use __bridge or __bridge_retained if I'm bridging an autoreleased object to Core Foundation? I'm not sure if it matters that the Objective-C convenience constructor is explicitly saved to an Objective-C variable on the previous line. Also, the approved answer says to only use __bridge_retained "if you want to manage the lifecycle" of the C object, which I think is wrong... I get the sense lots of people are using __bridge_retained because they have to manage the lifecycle themselves.
- Where and how to __bridge Approved answer has helpful summary, but focuses on non-retained example.
PS. Please don't judge me because I'm using Helvetica... :)
Edit:
When I use __bridge_retained, and do static analyzer, I get this complaint:
"Property returns a Core Foundation object with a +0 retain count. Incorrect decrement of the reference count of an object that is not owned at this point by the caller."
(The mDelegate and IS_ARC lines are, I believe, irrelevant to this issue.)
So there's something I'm fundamentally not understanding correctly...