ARCとブリッジキャスト


166

ARCでは、にキャストできなくなりましCGColorRefid。私はブリッジキャストをする必要があることを学びました。clang docsによると:

ブリッジ・キャスト Cスタイルのキャストは、3つのキーワードの一つでアノテートされています。

(__bridge T) opオペランドを宛先の型にキャストしますTT が保持可能なオブジェクトポインタ型の場合、保持op不可能なポインタ型でなければなりません。もしT非保持可能ポインタ型である場合、opは保持できるオブジェクトのポインタ型を持っている必要があります。それ以外の場合、キャストは不正です。所有権の譲渡はなく、ARCは保持操作を挿入しません。

(__bridge_retained T) op保持可能なオブジェクトポインタ型である必要があるオペランドを、保持不可能なポインタ型である宛先型にキャストします。ARCはローカル値の通常の最適化に従って値を保持し、受信者はその+1のバランスを取る責任があります。

(__bridge_transfer T) op保持不可能なポインタ型でなければならないオペランドを、保持可能なオブジェクトポインタ型でなければならない宛先型にキャストします。ARCは、ローカル値の通常の最適化に従って、囲んでいる完全式の終わりに値を解放します。

これらのキャストは、ARC制御の内外にオブジェクトを転送するために必要です。保持可能なオブジェクトポインターの変換に関するセクションの理論的根拠を参照してください。

__bridge_retainedまたは__bridge_transferキャストを使用して、ARCに不均衡な保持または解放をそれぞれ放出するように説得することは、不適切な形式です。

それぞれどのような状況で使用しますか?

例えば、CAGradientLayer持ちcolorsの配列プロパティ受け付けるCGColorRef秒。私は__brigeここで使用するべきだと思いますが、正確になぜすべきか(すべきでないか)は明確ではありません。


17
WWDC 2011セッション323はもう見ましたか?それは私がここでできるよりはるかに良いARCを説明しています。最初から最後まですべての詳細をカバーしています。すべてのMac / iOS開発者にとって必見のセッションです。
rbrown 2011

あまりにもこのかもしれないのヘルプ:stackoverflow.com/questions/14352494/...
ユアン・メラー

WWDCセッションへのリンク、見つけるのは簡単ではありませんでした:developer.apple.com/videos/play/wwdc2011/323 –関連ビットは23:15に
Daniel

回答:


215

説明がわかりにくいことに同意します。把握したばかりなので、まとめてみます。

  • (__bridge_transfer <NSType>) opまたはCFBridgingRelease(op)CFTypeRefそれをARCに転送するときに保持カウントを消費するために使用されます。これは、id someObj = (__bridge <NSType>) op; CFRelease(op);

  • (__bridge_retained <CFType>) opまたは、CFランドに+1の保持カウントを与えながらCFBridgingRetain(op)引き渡すために使用されNSObjectます。CFTypeRefこの方法で作成したは、の結果を処理する場合と同じように処理する必要がありますCFStringCreateCopy()。これは、CFRetain((__bridge CFType)op); CFTypeRef someTypeRef = (__bridge CFType)op;

  • __bridgeポインターランドとObjective-Cオブジェクトランドの間をキャストするだけです。上記の変換を使用する傾向がない場合は、これを使用してください。

多分これは役に立ちます。私自身、私CFBridging…は普通のキャストよりもかなりマクロを好みます。


__bridge_transferを使用すると、オブジェクトの保持カウントは弧によって1ずつ増加しますか?そうしないと、CFRelease()が呼び出された瞬間にオブジェクトがなくなって、何も指していないように見えます。同様に、__ bridge_retainを使用すると、ARCはopの保持カウントを1つ減らしますか?そうでなければ、オブジェクトが適切に解放されることは決してないようです。
Tony

2
いったんARCランドに入ると、保持カウントについてはもう考えず、強い参照と弱い参照についてのみ考えます。
モンキーダム

4
あなたはアークと非アーク環境間でオブジェクトを移行しているときいや、あなたはアーク土地でのみ強い/弱い場合は十分だろう、しかし、あなたはまだボンネットの下にカウント意味合いを保持について考える必要がない
トニー・

3
あんまり。ARCの土地に出入りすることについて考える必要があります。そして、これはオートリリースの把握に非常によく似ています。(興味深いことに、ARCは、オブジェクトをディクショナリから取り出し、使用する前に削除するなどの一般的なパターンを修正します。)
monkeydom

3
アナライザーツール(shift +コマンド+ B)を使用すると、現在のコードがメモリリークしている場合に自然言語でわかるので、この種の疑問を解決するのに役立ちます。そうである場合は、おそらく保持型キャストを使用していますが、非保持型キャストを使用する必要があります。アナライザーがそのコード行の何についても警告しない場合は、おそらく現在のコードでうまく機能していると
思い

55

iOSのドキュメントで、わかりやすいと思う別の説明を見つけました。

  • __bridge 所有権を譲渡せずにObjective-CとCore Foundationの間でポインターを転送します。

  • __bridge_retained (CFBridgingRetain)Objective-CポインターをCore Foundationにキャストしますポインターに所有権もあなたに譲渡します。

    あなたは責任があるオブジェクトの放棄所有権にCFReleaseまたは関連する機能を呼び出すため。

  • __bridge_transfer (CFBridgingRelease)移動非Objective-CのポインタのObjective-Cに、またARCに所有権を転送します。

    ARCは、オブジェクトの所有権を放棄する責任があります。

出典:フリーブリッジタイプ


33

後続として、この特定のケースでは、iOSを使用している場合、AppleはUIColorとその-CGColorメソッドを使用してCGColorRefをcolorsNSArray に返すことを推奨しています。ではARCリリースノートへの移行、セクションの下に、法などを用いていることを示している「コンパイラは、CFはココアメソッドから返されるオブジェクトのハンドル」-CGColor、Core Foundationオブジェクトを返す、コンパイラによって自動的に適切に処理されるいます。

したがって、次のようなコードを使用することをお勧めします。

CAGradientLayer *gradientLayer = (CAGradientLayer *)[self layer];
gradientLayer.colors = [NSArray arrayWithObjects:(id)[[UIColor darkGrayColor] CGColor],
                                                 (id)[[UIColor lightGrayColor] CGColor], nil];

現在のところ、Appleのサンプルコードには上記の(id)キャストがありません。これは、コンパイラエラーを回避するために依然として必要です。


通常は、必要に応じて、最初のオブジェクトをすべてではなく(id)にキャストするだけで済みます。
Philippe Sabourin、2011

1
この質問では、ARCを使用したキャストについて質問します。ここで、貼り付けたコードは無効です。
Joey Hagedorn、2012年

11
@JoeyHagedorn-おそらく、私の回答の最初の文でARCドキュメントへの私の参照を見逃したかもしれませんが、ARCでこれが有効であるだけでなく、これらのUIColorコンバーターメソッドからNSArrayへのCGColorRef参照を提供するための推奨アプローチです。私や他の多くの人は、ARC対応アプリケーション内でこの正確なコードを使用しています。Core Foundationオブジェクトを返すメソッドから(id)への即時キャストは、そのオブジェクトをARCに自動的にブリッジします。
ブラッド・ラーソン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.