ARCでNSString
からCFStringRef
を取得する正しい方法を理解しようとしていますか? ARCでCFStringRef
からNSString
へ反対方向に移動する場合も同じですか?
メモリリークを発生させずにこれを行う正しい方法は何ですか?
通常
NSString *yourFriendlyNSString = (__bridge NSString *)yourFriendlyCFString;
そして
CFStringRef yourFriendlyCFString = (__bridge CFStringRef)yourFriendlyNSString;
__bridge
キーワードがある理由を知りたい場合は、 Appleドキュメント を参照できます。そこにあります:
__bridge
は、Objective-CとCore Foundationの間で所有権を譲渡せずにポインターを転送します。
__bridge_retained
またはCFBridgingRetain
はObjective-CポインタをキャストしますCore Foundationポインターであり、所有権もあなたに譲渡します。 CFReleaseまたは関連する関数を呼び出して、オブジェクトの所有権を放棄する必要があります。
__bridge_transfer
またはCFBridgingRelease
は非目的Cを移動しますObjective-Cへのポインタ。所有権をARCに転送します。 ARCは、オブジェクトの所有権を放棄する責任があります。
つまり、上記の場合、所有権を変更せずにオブジェクトをキャストします。これは、どちらの場合も、文字列のメモリの処理を担当することを意味します。
何らかの理由で所有権を譲渡したい場合もあります。
たとえば、次のスニペットを考えます
- (void)sayHi {
CFStringRef str = CFStringCreateWithCString(NULL, "Hello World!", kCFStringEncodingMacRoman);
NSString * aNSString = (__bridge NSString *)str;
NSLog(@"%@", aNSString);
CFRelease(str); //you have to release the string because you created it with a 'Create' CF function
}
そのような場合、キャスト時に所有権を譲渡することでCFRelease
を保存することができます。
- (void)sayHi {
CFStringRef str = CFStringCreateWithCString(NULL, "Hello World!", kCFStringEncodingMacRoman);
NSString * aNSString = (__bridge_transfer NSString *)str;
// or alternatively
NSString * aNSString = (NSString *)CFBridgingRelease(str);
NSLog(@"%@", aNSString);
}
str
の所有権が譲渡されたため、ARCがメモリを解放して解放します。
他の方法では、NSString *
キャストを使用して__bridge_retained
をCFString
にキャストできるため、オブジェクトを所有し、CFRelease
を使用して明示的に解放する必要があります。
それを包むためにあなたが持つことができます
// Don't transfer ownership. You won't have to call `CFRelease`
CFStringRef str = (__bridge CFStringRef)string;
// Transfer ownership (i.e. get ARC out of the way). The object is now yours and you must call `CFRelease` when you're done with it
CFStringRef str = (__bridge_retained CFStringRef)string // you will have to call `CFRelease`
// Don't transfer ownership. ARC stays out of the way, and you must call `CFRelease` on `str` if appropriate (depending on how the `CFString` was created)
NSString *string = (__bridge NSString *)str;
// Transfer ownership to ARC. ARC kicks in and it's now in charge of releasing the string object. You won't have to explicitly call `CFRelease` on `str`
NSString *string = (__bridge_transfer NSString *)str;