0

I use JSON for implementing Facebook in an app and I'm just making my code ARC-friendly. However, when I make lines such as this one

CFStringAppendCharacters((CFMutableStringRef)json, &uc, 1);

become

CFStringAppendCharacters((__bridge CFMutableStringRef)json, &uc, 1);

my app is no longer able to pull my photo albums (I allow the user to log into Facebook and I then display his albums in order for him/her to get a picture to later use in the app).

This is the entire code that is not appreciated by ARC - (could anyone give me a hint how to bridge it please?)

NSString* escaped_value = (NSString *)CFURLCreateStringByAddingPercentEscapes(
                              NULL, /* allocator */
                              (CFStringRef)value,
                              NULL, /* charactersToLeaveUnescaped */
                              (CFStringRef)@"!*'();:@&=+$,/?%#[]",
                              kCFStringEncodingUTF8);

Does anyone know how I could port the JSON framework for ARC use?

Sorin Cioban
  • 2,237
  • 6
  • 30
  • 36
  • Which JSON framework? And why not just exclude this code from ARC? – Firoze Lafeer Jan 20 '12 at 23:10
  • 1
    Or, if you're going ARC then why not just use NSJSONSerialization? It's only 4.3 support you'll lose. – Tommy Jan 20 '12 at 23:12
  • I tried excluding it from ARC but then my Facebook API crashes. If I'm going to use NSJSONSerialization, do I need to do the parsing myself or is it all there already? I wouldn't necessarily like to rewrite functionality I already have. How does NSJSONSerialization work? – Sorin Cioban Jan 20 '12 at 23:15
  • Check and see if the latest Facebook SDK (which comes with the SBJSON library built into it) is ARC compatible. – Michael Dautermann Jan 20 '12 at 23:26
  • NSJSONSerialization does the parsing for you, and is built into Cocoa. It's probably a good choice. – Catfish_Man Jan 20 '12 at 23:42
  • Made a call to NSJSONSerialization and it worked like magic :) Thanks!! – Sorin Cioban Jan 20 '12 at 23:46

1 Answers1

0

I see in your comment that you just decided to go with NSJSONSerialization, that will definitely work. But to actually answer your question.

Using the __bridge cast is easy when you think about the memory management involved. __bridge just casts without doing any memory management operations for you; __bridge_transfer also casts, but it decrements the retain count of the object being casted. So with that in mind, your function call can be broken down like so:

CFStringRef originalValue = (__bridge CFStringRef)value;// Only __bridge required because ownership not changing
CFStringRef escapeChars = (CFStringRef)@"!*'();:@&=+$,/?%#[]";// __bridge not required for string literal
CFStringRef escaped_CFString = CFURLCreateStringByAddingPercentEscapes(NULL, originalValue, NULL, escapeChars, kCFStringEncodingUTF8);// returns a CFStringRef that YOU own.
NSString *escaped_value = (__bridge_transfer NSString *)escaped_CFString; // __bridge_transfer tells the compiler to send a release call to escaped_CFString.

Now that you see what's happening you can safely stack the calls like this:

NSString* escaped_value = (__bridge_transfer NSString *)CFURLCreateStringByAddingPercentEscapes(NULL,(__bridge CFStringRef)value,NULL,(CFStringRef)@"!*'();:@&=+$,/?%#[]",kCFStringEncodingUTF8);

Note that this method is still not that reliable. A more complete solution can be found in Dave DeLong's answer to this question.

Community
  • 1
  • 1
NJones
  • 27,139
  • 8
  • 70
  • 88