1. ホーム
  2. objective-c

[解決済み] ARCでNSStringからCFStringRef、CFStringRefからNSString?

2023-03-14 12:31:13

質問

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

メモリリークを発生させない正しい方法は何ですか?

どのように解決するのですか?

一般的に

NSString *yourFriendlyNSString = (__bridge NSString *)yourFriendlyCFString;

CFStringRef yourFriendlyCFString = (__bridge CFStringRef)yourFriendlyNSString;

さて、もしあなたが、なぜ __bridge キーワードがある理由を知りたい場合は アップルのドキュメント . そこに書いてあります。

__bridge は、Objective-C と Core Foundation の間で、所有権の移動なしにポインタを転送します。

__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 .


最後に、あなたは

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;