2
- (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 @"";
}

我不熟悉 CFTypes(除了知道它们是什么)。这是我从互联网上获得的代码,我不得不费力地让它在 ARC 中工作。我收到了潜在的泄漏警告,但不知道如何解决。建议?

4

3 回答 3

8

是的,这是内存泄漏。你的意思是使用CFBridgingRelease()而不是__bridge.

由创建的对象CFURLCreateStringByAddingPercentEscapes有一个额外的保留,因为它包含Create. 您需要将该对象传输到 ARC,让它知道添加一个额外的版本,这就是这样CFBridgingRelease()做的。

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

您确实使用__bridge了传入的字符串,因为您没有将其传输到 Core Foundation。您只是要求 Core Foundation 使用它,而 ARC 继续拥有它。当您“转让”所有权时,您通常的意思是“这个对象曾经是 Core Foundation,现在是 ARC”(反之亦然)。这就是正在发生的事情newString

我用结果交换了长的 NS-to-CF 编码函数,只是为了让它更短。

于 2012-05-02T00:40:39.167 回答
0

返回字符串的自动释放版本,CFStringRef可以转换为NSString,反之亦然,这也意味着您可以将其视为普通版本NSString,从而自动释放它(如果您对此感兴趣,您应该阅读有关部分之间的免费桥接FoundationCore Foundation)

于 2012-05-02T00:39:55.270 回答
0

另一种方法是使用 __bridge_transfer 而不是 __bridge ,如下所示:

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

请参阅此问题中的更多信息:ARC 的正确桥接?

于 2015-09-23T03:29:26.463 回答