7

考虑这个简单的方法;它是 NSString 上的一个类别。

- (NSString *)stringByUrlEncoding
{
    CFStringRef newString = CFURLCreateStringByAddingPercentEscapes(NULL, (CFStringRef)self, NULL, (CFStringRef)@"!*'\"();:@&=+$,/?%#[]% ", kCFStringEncodingUTF8);
    NSString *returnString = (__bridge NSString *)newString;
    CFRelease(newString);
    return returnString;
}

它的工作是为 URL 编码=转换成%3D等,但这与这个问题无关。

关于内存管理的几个问题:

  1. 调用后CFRelease(newString);,我仍然可以po newString在调试器中看到字符串。这是否意味着它没有被正确释放?

  2. 当我将转换的 CFStringRefs 传递给 CFURLCreateStringByAddingPercentEscapes 的参数时,(例如(CFStringRef)self,例如)我相信我不需要将它们存储到变量中,然后由于“免费桥接”而 CFRelease 它们。它是否正确?

  3. 如果它是 CGImageRef 而不是 CFStringRef,#2 的答案会改变吗?为什么CGImageRef有自己的CGImageRelease函数,却没有CFStringRelease方法?

  4. 为了确保我的理解__bridge_transfer是正确的,这个修改后的代码是否相同?

    - (NSString *)stringByUrlEncoding
    {
        CFStringRef newString = CFURLCreateStringByAddingPercentEscapes(NULL, (CFStringRef)self, NULL, (CFStringRef)@"!*'\"();:@&=+$,/?%#[]% ", kCFStringEncodingUTF8);
        NSString *returnString = (__bridge_transfer NSString *)newString;
        // CFRelease(newString);
        return returnString;
    }
    
4

1 回答 1

2

至于你的问题:

1)您没有足够的信息来知道是否newString应该被释放。例如,如果实际上不需要字符替换,则CFURLCreateStringByAddingPercentEscapes返回等效于[self retain];是合理的。这只是一个例子。更广泛的观点是“你不知道”。这里的正常方法是使用 Instruments 来查找堆增长和泄漏。更多信息,谷歌“retainCount useless”(这里不再赘述。)

2) 是的。

3)CGImageRef不是免费桥接,但是,据我了解,CFRetain应该CFRelease可以工作。CFReleaseCGImageRelease这里的区别在于参数CFRelease不能是NULL,而CGImageRelease将容忍NULL参数。

4)__bridge_transfer是此处使用的适当注释。这会将 +1 保留计数从 ARC 未处理的一侧“转移”到它确实处理的一侧。换句话说,__bridge_transfer只是告诉 ARC 它需要release为此指针创建一个调用,即使它从未生成过retain.

于 2013-02-19T19:21:05.720 回答