Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to convert CFStringRef to NSString?

NSString and CFStringRef are "Toll free bridged", meaning that you can simply typecast between them.

For example:

CFStringRef aCFString = (CFStringRef)aNSString;

works perfectly and transparently. Likewise:

NSString *aNSString = (NSString *)aCFString;

The previous syntax was for MRC. If you're using ARC, the new casting syntax is as follows:

NSString *aNSString = (__bridge NSString *)aCFString;

works as well. The key thing to note is that CoreFoundation will often return objects with +1 reference counts, meaning that they need to be released (all CF[Type]Create format functions do this).

The nice thing is that in Cocoa you can safely use autorelease or release to free them up.


If you're using ARC in recent versions of Mac OS X/Objective C, it's real easy:

NSString *happyString = (NSString *)CFBridgingRelease(sadString);

However, Xcode will happily warn you when you try to toll free bridge CFString to NSString and offer to automatically wrap it in CFBridgingRelease(), which you can accept and let it automatically insert the wrapper for you if you click the option.


They are equivalent, so you can just cast the CFStringRef:

NSString *aNSString = (NSString*)aCFString;

For more info, see Toll-Free Bridged Types.


Actually, you shouldn't use Cocoa retain, release, autorelease on Core Foundation objects in generality. If you're using Garbage Collection (only on Mac OS X for now), those retain, release, autorelease calls are all no-ops. Hence memory leaks.

From Apple http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/GarbageCollection/Articles/gcCoreFoundation.html:

It is important to appreciate the asymmetry between Core Foundation and Cocoa—where retain, release, and autorelease are no-ops. If, for example, you have balanced a CFCreate… with release or autorelease, you will leak the object in a garbage collected environment:

NSString *myString = (NSString *)CFStringCreate...(...);
// do interesting things with myString...
[myString release]; // leaked in a garbage collected environment

Conversely, using CFRelease to release an object you have previously retained using retain will result in a reference count underflow error.


PS: can't seem to comment on Peter Hosey's answer - sorry for adding my own unnecessarily.


I'll add that not only can you go from CFString to NSString with only a type-cast, but it works the other way as well. You can drop the CFStringCreateWithCString message, which is one fewer thing you need to release later. (CF uses Create where Cocoa uses alloc, so either way, you would have needed to release it.)

The resulting code:

NSString *escapedString;
NSString *unescapedString = [(NSString *) CFXMLCreateStringByUnescapingEntities(NULL, (CFStringRef) escapedString, NULL) autorelease];

I was having an issue with ARC and the retain count of CFStrings. Using NilObjects answer with a slight tweak worked perfect for me. I just added retained eg.

CFStringRef cfstringRef = (__bridge_retained  CFStringRef)aNsString;