- (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中运行。我有潜在的泄漏警告,我不知道如何解决它。建议?
答案 0 :(得分: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编码函数换成了结果,只是为了缩短它。
答案 1 :(得分:0)
返回字符串的自动释放版本,CFStringRef
可以转换为NSString
,反之亦然,这也意味着您可以像普通NSString
一样对待它,从而自动释放它(如果您对此感兴趣,请阅读Foundation
和Core Foundation
部分之间的免费桥接
答案 2 :(得分:0)
另一种方法是使用__bridge_transfer而不是__bridge,如下所示:
NSString *newString = (__bridge_transfer NSString *)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (__bridge CFStringRef)string, NULL, CFSTR(":/?#[]@!$ &'()*+,;=\"<>%{}|\\^~`"), CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncoding));
在此问题中查看更多信息:Correct bridging for ARC?