少し混乱しています。私が読んだすべての場所で、ARCを使用する場合でも、意味のあるコア基盤オブジェクトをリリースする必要があることを示唆しています。ARCはそれらを管理しません。ただし、CFRelease
を使用したCFメソッド/オブジェクトを使用するメソッドがありますが、それが原因でアプリがクラッシュしました。 CFRelease
sのコメントを外すと問題は解決しますが、メモリリークが発生したと思いますか?
誰かがリリースする必要があるものとリリースしないもの、またはこのコードで間違っている他の何かを説明できますか?
+ (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
呼び出しは、前述のように問題を修正しますが、それが間違っていることはわかっています。私は何をすべきですか?
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;
}
チェックアウト WWDC 2012-Modern Objective-C これはCoreFoundationオブジェクトとARCの新しいガイドラインの概要を示しています。そのビデオの37時35分頃です。つまり、名前にCopy
またはCreate
が含まれるCoreFoundation関数は、所有権をアプリに譲渡したオブジェクトを作成し、アプリはそれを解放する責任があります。
とにかく、名前にCopy
またはCreate
が含まれるCoreFoundationメソッドを介して所有権が譲渡された場合は、完了したらCFRelease
を使用して手動で解放できます。 、または、より簡単に、所有権をARCに譲渡して、それを処理させることができます。歴史的に、所有権をARCに譲渡するために、__bridge_transfer
を使用していましたが、現在はCFBridgingRelease
を推奨しています(後者は前者の単なるマクロですが)。そして、明らかに、名前にCopy
またはCreate
が含まれる関数以外のメカニズムを介して取得した、Core Foundationオブジェクトがある場合は、CFRelease
も使用しないでください。また、所有権をARCに譲渡することもありません。
実例として、このメソッドはあなたが望むことを達成します:
+ (NSString *) fileExtensionForMimeType:(NSString *)type {
NSString *uti = CFBridgingRelease(UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType,
(__bridge CFStringRef)type,
NULL));
return CFBridgingRelease(UTTypeCopyPreferredTagWithClass((__bridge CFStringRef)uti,
kUTTagClassFilenameExtension));
}
一般的に言って、最初のCFRelease(mimeType)行にコメントを付け、次の2行(CFRelease(uti)とCFRelease(extension))のコメントを外す必要があると思います。 NSStringを入力するためにフリーダイヤルブリッジをキャストすると、ARCがリリースを処理します。ただし、utiと拡張子はCFStringとして作成/コピーされます。 ARCはそれらの処理方法を認識しないため(ARCはNSObjectのコンパイラ機能であることを思い出してください)、CFリリースする必要があります。