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

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

它的工作是将=转换为%3D等以进行URL编码,但这与该问题无关。

有关内存管理的几个问题:
  • 调用CFRelease(newString);之后,我仍然可以在调试器中使用po newString并查看字符串。这是否意味着不能正确释放?
  • 当我将强制转换的CFStringRefs传递给CFURLCreateStringByAddingPercentEscapes的参数时(例如(CFStringRef)self),我认为由于“免费桥接”,我不需要将它们存储到变量中然后CFRelease它们。这样对吗?
  • 如果它是CGImageRef而不是CFStringRef,对第二个问题的答案是否会改变?为什么CGImageRef有自己的CGImageRelease函数,但是没有CFStringRelease方法?
  • 为确保我对__bridge_transfer的理解正确,此修改后的代码是否相同?
    - (NSString *)stringByUrlEncoding
    {
        CFStringRef newString = CFURLCreateStringByAddingPercentEscapes(NULL, (CFStringRef)self, NULL, (CFStringRef)@"!*'\"();:@&=+$,/?%#[]% ", kCFStringEncodingUTF8);
        NSString *returnString = (__bridge_transfer NSString *)newString;
        // CFRelease(newString);
        return returnString;
    }
    
  • 最佳答案

    关于您的问题:

    1)您没有足够的信息来知道newString是否应该被释放。例如,如果实际上不需要字符替换,那么CFURLCreateStringByAddingPercentEscapes返回相当于[self retain]的代码是合理的;这只是一个例子。更广泛的意义是“你不知道”。此处通常的方法是使用Instruments查找堆增长和泄漏。欲了解更多信息,谷歌“retainCount没用”(我不会在这里重新哈希。)

    2)是的。

    3)CGImageRef并非免费桥接,但是据我所知,CFRetainCFRelease应该可以工作。此处CFReleaseCGImageRelease的区别在于CFRelease的参数不能为NULL,而CGImageRelease可以接受NULL参数。

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

    关于objective-c - 使用CFStringRef和CFRelease进行适当的内存管理,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/14965354/

    10-10 21:10