I'm slightly confused. Everywhere I've read, suggest that when using ARC, you still need to release core foundation objects which makes sense, ARC doesn't manage them. However, I've got a method which uses some CF methods/objects which I used CFRelease
on, but that then caused the app to crash. Uncommenting my CFRelease
s fixes the issue but then I'm assuming I've got a memory leak?
Could someone please explain which things need releasing and which don't, or anything else that's wrong with this code?
+ (NSString *) fileExtensionForMimeType:(NSString *)type
{
CFStringRef mimeType = (__bridge CFStringRef)type;
CFStringRef uti = UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType, mimeType, NULL);
CFStringRef extension = UTTypeCopyPreferredTagWithClass(uti, kUTTagClassFilenameExtension);
NSString *ext = (__bridge NSString *)extension;
// CFRelease(mimeType);
// CFRelease(uti);
// CFRelease(extension);
return ext;
}
The three commented out CFRelease
calls fix the issue as mentioned, but I know it's wrong. What should I be doing?
You can't release
mimeType
because you don't own it. You didn't transfer ownership with the__bridge
cast.You should be releasing
uti
since you have created it.You should also release
extension
since you created it as well, but that will likely cause issues withext
. Instead, transfer ownership toext
.I'd suggest the following:
Check out WWDC 2012 - Modern Objective-C which outlines new guidelines for Core Foundation objects and ARC. It's about 37:35 into that video. In short, Core Foundation functions with
Copy
orCreate
in the name create an object that has transferred ownership to your app, and your app is responsible for releasing it.Anyway, if ownership has been transferred via a Core Foundation method with
Copy
orCreate
in the name, you can either release manually it withCFRelease
when you're done with it, or, easier, you can transfer ownership to ARC and let it take care of it. Historically, to transfer ownership to ARC, we used__bridge_transfer
, but they now recommendCFBridgingRelease
(though the latter is just a macro for the former). And, obviously, if you have some Core Foundation object that you retrieved via some other mechanism other than a function withCopy
orCreate
in the name, you should neitherCFRelease
it nor transfer ownership to ARC.By way of illustration, this method accomplishes what you want:
In generally speaking, I think you should try to comment the first CFRelease(mimeType) line, and uncomment the followed two lines: CFRelease(uti) and CFRelease(extension). You cast a toll-free bridge to input NSString and ARC will handle the release. But the uti and extension is created/copied as CFString. ARC will not know how to handle them (remember ARC is a compiler feature for NSObject), so you need to CF release them.