ARCでNSString
からを取得する正しい方法を理解しようとしていますCFStringRef
か?、反対の方向に行くために同じCFStringRef
にNSString
ARCに?
メモリリークを発生させずにこれを行う正しい方法は何ですか?
ARCでNSString
からを取得する正しい方法を理解しようとしていますCFStringRef
か?、反対の方向に行くために同じCFStringRef
にNSString
ARCに?
メモリリークを発生させずにこれを行う正しい方法は何ですか?
retain
INGのとrelease
オブジェクトを-ing、我々は今のような「美しい」キャストを使用しなければならない__bridge_transfer
、__unsafe_unretained
と__autoreleasing
。誰もそのための時間がありません。(そして真剣に、それは読みにくいです。私の意見では、それはメモリ管理をまったく促進しませんでした。)
回答:
通常、
NSString *yourFriendlyNSString = (__bridge NSString *)yourFriendlyCFString;
そして
CFStringRef yourFriendlyCFString = (__bridge CFStringRef)yourFriendlyNSString;
ここで、__bridge
キーワードが存在する理由を知りたい場合は、Appleのドキュメントを参照してください。そこにあなたが見つけるでしょう:
__bridge
所有権を譲渡せずに、Objective-CとCoreFoundationの間でポインターを譲渡します。
__bridge_retained
またはCFBridgingRetain
、Objective-CポインターをCore Foundationポインターにキャストし、所有権をユーザーに譲渡します。CFReleaseまたは関連する関数を呼び出して、オブジェクトの所有権を放棄する必要があります。
__bridge_transfer
またはCFBridgingRelease
、Objective-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 *
してCFString
をに__bridge_retained
キャストすることもできます。そのため、オブジェクトを所有し、を使用してオブジェクトを明示的に解放する必要があります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;
NSString->CFString
、を使用する必要があります__bridge
。ただし、の場合はCFString->NSString
、を使用する必要があります__bride_transfer
。?そして、CFRelease
必要のないときに使用すれば、副作用もあります。ありがとう:)
CFRelease
保持/解放操作の不一致が発生し、最終的にNULL
ポインタが解放されるため、エクストラはプログラムを合理的にクラッシュさせるはずです。
CFStringRef foo (__bridge CFStringRef)theNSString;
およびNSString *bar = (__bridge NSString *)theCFString;