35

少し混乱しています。私が読んだすべての場所で、ARCを使用する場合でも、意味のあるコアFoundationオブジェクトをリリースする必要があることを示唆していますが、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;
}

コメントアウトされた3つのCFRelease呼び出しは、前述のように問題を修正しますが、それが間違っていることはわかっています。私は何をすべきですか?

4

3 に答える 3

39

所有していないため、リリースできませ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;
}
于 2012-12-28T04:00:19.307 に答える
16

Core Foundation オブジェクトと ARC の新しいガイドラインを概説するWWDC 2012 - Modern Objective-Cを確認してください。その動画の 37:35 あたりです。Copyつまり、または名前に含まれるCore Foundation 関数はCreate、所有権をアプリに譲渡したオブジェクトを作成し、アプリはそれを解放する責任があります。

とにかく、所有権が Core Foundation メソッドを介してCopyまたはCreate名前で譲渡された場合、完了したら手動で解放するCFReleaseか、より簡単に、所有権を ARC に譲渡して処理させることができます。 . 歴史的に、所有権を ARC に譲渡するには を使用__bridge_transferしていましたが、現在は推奨されてCFBridgingReleaseいます (ただし、後者は前者の単なるマクロです)。そして、明らかに、関数以外のメカニズムを介して取得した Core Foundation オブジェクトがある場合は、そのオブジェクトCopyまたはその所有権を ARC に譲渡しCreateないでください。CFRelease

例として、このメソッドは目的を達成します。

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

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

    return CFBridgingRelease(UTTypeCopyPreferredTagWithClass((__bridge CFStringRef)uti,
                                                             kUTTagClassFilenameExtension));
}
于 2012-12-28T04:23:11.960 に答える
0

一般的に言えば、最初の CFRelease(mimeType) 行にコメントを付けて、それに続く 2 行の CFRelease(uti) と CFRelease(extension) のコメントを外すべきだと思います。無料のブリッジをキャストして NSString を入力すると、ARC がリリースを処理します。ただし、ユーティリティと拡張機能は CFString として作成/コピーされます。ARC はそれらの処理方法を認識しないため (ARC は NSObject のコンパイラ機能であることを思い出してください)、CF でリリースする必要があります。

于 2012-12-28T04:03:06.737 に答える