web-dev-qa-db-ja.com

NSString to CFStringRefおよびCFStringRef to NSString to ARC?

ARCでNSStringからCFStringRefを取得する正しい方法を理解しようとしていますか? ARCでCFStringRefからNSStringへ反対方向に移動する場合も同じですか?

メモリリークを発生させずにこれを行う正しい方法は何ですか?

79
zumzum

通常

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_retainedCFStringにキャストできるため、オブジェクトを所有し、CFReleaseを使用して明示的に解放する必要があります。


それを包むためにあなたが持つことができます

NSString→CFString

// 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`

CFString→NSString

// 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;
163