96

I am trying to understand the correct way of getting an NSString from a CFStringRef in ARC? Same for going the opposite direction, CFStringRef to NSString in ARC?

What is the correct way to do this without creating memory leaks?

Gabriele Petronella
  • 106,943
  • 21
  • 217
  • 235
zumzum
  • 17,984
  • 26
  • 111
  • 172
  • 4
    `CFStringRef foo (__bridge CFStringRef)theNSString;` and `NSString *bar = (__bridge NSString *)theCFString;` –  Jun 21 '13 at 03:43
  • Could you explain what is really happening in details when those two options are used? – zumzum Jun 21 '13 at 14:07
  • Not quite. I don't use ARC, so all I know is that you have to do this, but not the *why.* –  Jun 21 '13 at 14:53
  • @H2CO3 out of curiosity, any particular reason why you don't use ARC? – Gabriele Petronella Jun 23 '13 at 01:34
  • 1
    @GabrielePetronella ARC was supposed to make coding easy, code shorter and more readable and reduce the possibility for human errors. So, now instead of having to take care of reference counts by `retain`ing and `release`-ing objects, we must now use "beautiful" casts like `__bridge_transfer`, `__unsafe_unretained` and `__autoreleasing`. Nobody ain't got no time for that. (And seriously, it's harder to read. In my opinion, it didn't facilitate memory management at all.) –  Jun 23 '13 at 04:27
  • 1
    @H2CO3 thank you for the answer. I strongly disagree, especially with the last sentence, but I respect your point of view :) – Gabriele Petronella Jun 23 '13 at 11:03
  • @GabrielePetronella is missing the point of ARC; to auto-reference count ObjC objects; and for that it's just fine (no casting required). The casts are only necessary to bridge the gap between the ObjC object and Core Foundation. – geowar Nov 08 '14 at 16:56

1 Answers1

192

Typically

NSString *yourFriendlyNSString = (__bridge NSString *)yourFriendlyCFString;

and

CFStringRef yourFriendlyCFString = (__bridge CFStringRef)yourFriendlyNSString;

Now, if you want to know why the __bridge keyword is there, you can refer to the Apple documentation. There you will find:

__bridge transfers a pointer between Objective-C and Core Foundation with no transfer of ownership.

__bridge_retained or CFBridgingRetain casts an Objective-C pointer to a Core Foundation pointer and also transfers ownership to you. You are responsible for calling CFRelease or a related function to relinquish ownership of the object.

__bridge_transfer or CFBridgingRelease moves a non-Objective-C pointer to Objective-C and also transfers ownership to ARC. ARC is responsible for relinquishing ownership of the object.

Which means that in the above cases you are casting the object without changing the ownership. This implies that in neither case you will be in charge of handling the memory of the strings.

There may also be the case in which you want to transfer the ownership for some reason.

For instance consider the following snippet

- (void)sayHi {
    CFStringRef str = CFStringCreateWithCString(NULL, "Hello World!", kCFStringEncodingMacRoman);

    NSString * aNSString = (__bridge NSString *)str;

    NSLog(@"%@", aNSString);

    CFRelease(str); //you have to release the string because you created it with a 'Create' CF function
}

in such a case you may want to save a CFRelease by transferring the ownership when casting.

- (void)sayHi {
    CFStringRef str = CFStringCreateWithCString(NULL, "Hello World!", kCFStringEncodingMacRoman);

    NSString * aNSString = (__bridge_transfer NSString *)str;
// or alternatively
    NSString * aNSString = (NSString *)CFBridgingRelease(str);

    NSLog(@"%@", aNSString);
}

The ownership of str has been transferred, so now ARC will kick in and release the memory for you.

On the other way around you can cast a NSString * to a CFString using a __bridge_retained cast, so that you will own the object and you'll have to explicitly release it by using CFRelease.


To wrap it up you can have

NSString → CFString

// Don't transfer ownership. You won't have to call `CFRelease`
CFStringRef str = (__bridge CFStringRef)string;

// Transfer ownership (i.e. get ARC out of the way). The object is now yours and you must call `CFRelease` when you're done with it
CFStringRef str = (__bridge_retained CFStringRef)string // you will have to call `CFRelease`

CFString → NSString

// Don't transfer ownership. ARC stays out of the way, and you must call `CFRelease` on `str` if appropriate (depending on how the `CFString` was created)
NSString *string = (__bridge NSString *)str;

// Transfer ownership to ARC. ARC kicks in and it's now in charge of releasing the string object. You won't have to explicitly call `CFRelease` on `str`
NSString *string = (__bridge_transfer NSString *)str;
Gabriele Petronella
  • 106,943
  • 21
  • 217
  • 235
  • Thanks you very much, this is not really intuitive, but thanks to you, lesson learned – Sulfkain May 13 '14 at 14:52
  • @: little question. so if we use ARC. when `NSString->CFString`, we should use `__bridge`. but when `CFString->NSString`, we should use `__bride_transfer`. ? And any side-effect, if we use `CFRelease` when we don't need too. thanks :) – hqt Aug 11 '14 at 03:41
  • @hqt, if you want the 'easy' way, yes what you say is correct. Also, an extra `CFRelease` should reasonably crash your program, since you will end up with mismatched retain/release operation, eventually releasing a `NULL` pointer. – Gabriele Petronella Aug 11 '14 at 16:01