ARC和CFRelease?

我有点困惑。 在我读过的地方,build议在使用ARC时,仍然需要释放核心基础对象,ARC不pipe理它们。 不过,我有一个方法,使用CF的方法/对象,我用CFRelease上,但是,然后导致应用程序崩溃。 取消注释我的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电话都提到了这个问题,但是我知道这是错误的。 我该怎么做?

你不能释放mimeType因为你不拥有它。 您没有将__bridge转换为所有权。

你应该释放uti因为你已经创build了它。

你也应该释放extension因为你也创build了它,但是这可能会导致ext问题。 相反,将所有权转移到ext

我会build议如下:

 + (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; } 

查看WWDC 2012 – 现代Objective-C ,它概述了Core Foundation对象和ARC的新指南。 这是约37:35的video。 简而言之,核心基金会在名称中使用“ Copy或“ Createfunction创build一个将所有权转移给您的应用程序的对象,并且您的应用程序负责将其释放。

无论如何,如果所有权已经通过名为CopyCreate的Core Foundation方法传输,那么您可以在完成后使用CFRelease手动CFRelease它,或者,更简单地,您可以将所有权转让给ARC,让它处理关心它。 从历史上看,为了将所有权转让给ARC,我们使用__bridge_transfer ,但是现在推荐CFBridgingRelease (尽pipe后者只是前者的一个macros)。 而且,显然,如果你有一些核心基础对象,你通过其他机制而不是名称中的CopyCreate函数来检索,你既不应该CFRelease它,也不应该将所有权转让给ARC。

举例来说,这个方法完成了你想要的:

 + (NSString *) fileExtensionForMimeType:(NSString *)type { NSString *uti = CFBridgingRelease(UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType, (__bridge CFStringRef)type, NULL)); return CFBridgingRelease(UTTypeCopyPreferredTagWithClass((__bridge CFStringRef)uti, kUTTagClassFilenameExtension)); } 

一般来说,我认为你应该尝试评论第一个CFRelease(mimeType)行,并取消注释后面的两行:CFRelease(uti)和CFRelease(extension)。 您投入一个免费的桥梁来inputNSString,ARC将处理该版本。 但uti和扩展名被创build/复制为CFString。 ARC不知道如何处理它们(记住ARC是NSObject的编译器function),所以你需要CF释放它们。