Question

- (NSString*)encodeURL:(NSString *)string
{
    NSString *newString = (__bridge NSString *)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (__bridge CFStringRef)string, NULL, CFSTR(":/?#[]@!$ &'()*+,;=\"<>%{}|\\^~`"), CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncoding));

    if (newString) 
    {
        return newString; // <-- potential leak here
    }

    return @"";
}

I'm not familiar with CFTypes (other than knowing what they are). This is code I got from the internet and have had to finagle a bit to get it to work in ARC. I'm getting a potential leak warning and I'm not sure how to fix it. Suggestions?

Was it helpful?

Solution

Yes, this is a memory leak. You meant to use CFBridgingRelease() rather than __bridge.

The object created by CFURLCreateStringByAddingPercentEscapes has an extra retain on it because it includes Create. You need to transfer that object to ARC, letting it know to add an extra release, that's what CFBridgingRelease() does.

NSString *newString = 
    CFBridgingRelease(
        CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, 
                                               (__bridge CFStringRef)string, 
                                               NULL,
                                               CFSTR(":/?#[]@!$ &'()*+,;=\"<>%{}|\\^~`"),           
                                               kCFStringEncodingUTF8));

You do use __bridge for the passed-in string because you're not transferring it to Core Foundation. You're just asking Core Foundation to use it while ARC continues to own it. When you "transfer" ownership, you generally mean "this object used to be Core Foundation, and now it's ARC" (or vice versa). That's what's happening to newString.

I swapped the long NS-to-CF encoding function with the result just to make it shorter.

OTHER TIPS

return a autoreleased version of the string, CFStringRef can be converted to NSString and vice versa, which also means that you can treat it like a normal NSString and thus autorelease it (if you are interested in this you should read about the toll free bridging between parts of Foundation and Core Foundation)

Another way is using __bridge_transfer instead of __bridge like this:

NSString *newString = (__bridge_transfer NSString *)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (__bridge CFStringRef)string, NULL, CFSTR(":/?#[]@!$ &'()*+,;=\"<>%{}|\\^~`"), CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncoding));

See more informations in this question: Correct bridging for ARC?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top