ARC和CFRelease?(ARC and CFRelease?)

2019-07-17 15:42发布

我稍微困惑。 我到处都读过,建议使用ARC时,你仍然需要释放核心基础对象这是有道理的,ARC不会管理它们。 但是,我有它使用一些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电话解决所提及的问题,但我知道这是错的。 我应该怎么做?

Answer 1:

你不能释放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;
}


Answer 2:

看看WWDC 2012 -现代的Objective-C ,其概述了核心基础对象和ARC的新准则。 这是关于37:35到该视频。 在短,Core Foundation的功能CopyCreate的名称创建已转移所有权转让给你的应用的对象,您的应用程序负责释放它。

无论如何,如果所有权已经通过Core Foundation的方法转移与CopyCreate的名称,您可以手动释放CFRelease当你用它做,或者更简单,你可以将所有权转让给ARC让它来呵护它。 从历史上看,将所有权转让给ARC,我们使用__bridge_transfer ,但他们现在建议CFBridgingRelease (尽管后者只是前者的宏)。 而且,很明显,如果您有通过比使用其他功能其他机制检索到的一些核心基础对象CopyCreate的名称,你应该既不CFRelease ,也没有将所有权转让给ARC。

通过图示的方式,这种方法实现你想要什么:

+ (NSString *) fileExtensionForMimeType:(NSString *)type {

    NSString *uti = CFBridgingRelease(UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType,
                                                                            (__bridge CFStringRef)type,
                                                                            NULL));

    return CFBridgingRelease(UTTypeCopyPreferredTagWithClass((__bridge CFStringRef)uti,
                                                             kUTTagClassFilenameExtension));
}


Answer 3:

在通常来说,我想你应该试评第一CFRelease(媒体类型)的线,并取消注释随后两行:CFRelease(UTI)和CFRelease(扩展)。 你投一个免费的桥梁,输入的NSString和ARC将手柄上的释放。 但UTI和延伸创建/复制为CFString字符串。 ARC将不知道如何处理它们(记住ARC是NSObject的编译器功能),所以你需要CF释放他们。



文章来源: ARC and CFRelease?