How to convert CFStringRef to NSString?

NSString *aNSString;
CFStringRef aCFString;
aCFString = CFStringCreateWithCString(NULL, [aNSString UTF8String], NSUTF8StringEncoding);
aCFString = CFXMLCreateStringByUnescapingEntities(NULL, aCFString, NULL);

How can I get a new NSString from aCFString?


Solution 1:

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.

Solution 2:

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.

Solution 3:

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

NSString *aNSString = (NSString*)aCFString;

For more info, see Toll-Free Bridged Types.

Solution 4:

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.