web-dev-qa-db-ja.com

ARCおよびブリッジキャスト

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

bridged castは、次の3つのキーワードのいずれかで注釈が付けられたCスタイルのキャストです。

(__bridge T) opは、オペランドを宛先タイプTにキャストします。 Tが保持可能なオブジェクトポインタータイプである場合、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を使用する必要がありますが、正確に私がすべき(またはすべきではない)理由は不明です。

163
Morrowless

説明がわかりにくいことに同意します。私はそれらを把握したばかりなので、要約しようとします:

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

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

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

たぶんこれは役に立ちます。私自身、CFBridging…マクロはプレーンキャストよりもかなり好みです。

215
monkeydom

IOSのドキュメントで、理解しやすいと思う別の説明を見つけました。

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

  • __bridge_retained (CFBridgingRetain)は、Objective-CポインターをCore Foundationポインタと所有権をあなたに譲渡します。

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

  • __bridge_transfer (CFBridgingRelease)は、non-Objective-CポインターをObjective-Cまた、所有権をARCに譲渡します。

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

ソース: Toll-Free Bridged Types

53
gregschlom

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

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

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

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

32
Brad Larson