CFRelease
的CF方法/对象,但这导致应用程序崩溃。取消注释我的CFRelease
修复了问题,但后来我假设我有内存泄漏?
有人可以解释哪些内容需要发布,哪些内容不需要,或者其他任何错误都可以解释?
+ (NSString *) fileExtensionForMimeType:(NSString *)type
{
CFStringRef mimeType = (__bridge CFStringRef)type;
CFStringRef uti = UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType, mimeType, NULL);
CFStringRef extension = UTTypeCopyPreferredTagWithClass(uti, kUTTagClassFilenameExtension);
NSString *ext = (__bridge NSString *)extension;
// CFRelease(mimeType);
// CFRelease(uti);
// CFRelease(extension);
return ext;
}
三个注释掉的CFRelease
来电解决了上述问题,但我知道这是错误的。我该怎么办?
答案 0 :(得分:36)
您无法释放mimeType
,因为您不拥有它。您没有使用__bridge
演员转移所有权。
您应该发布uti
,因为您已经创建了它。
您也应该发布extension
,因为您也创建了ext
,但这可能会导致ext
出现问题。相反,将所有权转移到+ (NSString *) fileExtensionForMimeType:(NSString *)type {
CFStringRef mimeType = (__bridge CFStringRef)type;
CFStringRef uti = UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType, mimeType, NULL);
CFStringRef extension = UTTypeCopyPreferredTagWithClass(uti, kUTTagClassFilenameExtension);
NSString *ext = (__bridge_transfer NSString *)extension;
// CFRelease(mimeType); // not owned
if (uti) CFRelease(uti);
// CFRelease(extension); // ownership was transferred
return ext;
}
。
我建议如下:
{{1}}
答案 1 :(得分:15)
查看WWDC 2012 - Modern Objective-C,其中概述了Core Foundation对象和ARC的新指南。该视频大概是37:35。简而言之,名称中Copy
或Create
的Core Foundation功能会创建一个将所有权转移到您的应用程序的对象,并且您的应用程序负责释放它。
无论如何,如果所有权已通过名为Copy
或Create
的Core Foundation方法转移,则可以在完成后使用CFRelease
手动释放所有权或者,更简单,您可以将所有权转让给ARC并让它来处理它。从历史上看,为了将所有权转移到ARC,我们使用__bridge_transfer
,但他们现在推荐CFBridgingRelease
(尽管后者只是前者的宏)。而且,显然,如果您有一些Core Foundation对象,您通过名称中包含Copy
或Create
的函数以外的其他机制检索,则您既不应CFRelease
也不应转让所有权到ARC。
通过举例说明,此方法可以实现您的目的:
+ (NSString *) fileExtensionForMimeType:(NSString *)type {
NSString *uti = CFBridgingRelease(UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType,
(__bridge CFStringRef)type,
NULL));
return CFBridgingRelease(UTTypeCopyPreferredTagWithClass((__bridge CFStringRef)uti,
kUTTagClassFilenameExtension));
}
答案 2 :(得分:0)
一般来说,我认为您应该尝试评论第一个CFRelease(mimeType)行,并取消注释后面两行:CFRelease(uti)和CFRelease(扩展名)。你建立一个免费的桥接器来输入NSString,ARC将处理这个版本。但是uti和扩展名是作为CFString创建/复制的。 ARC不知道如何处理它们(记住ARC是NSObject的编译器功能),所以你需要CF发布它们。