9

ご存知のように、ARC では__bridgeid を に変換するためにが必要void *です。

void *t = (void *)self;           // ERROR: Cast of ... requires a bridged cast
void *t = (__bridge void *)self;  // CORRECT

C 関数呼び出しも同様です。

void f(void *t) {
  ....
}

f((void *)self);           // ERROR
f((__bridge void *)self);  // CORRECT

これはメソッドにも当てはまると思います。実際、このBeginning ARC in iOS 5 Tutorialは次の例を示しており、必要であると述べてい__bridgeます。

MyClass *myObject = [[MyClass alloc] init];
[UIView beginAnimations:nil context:(__bridge void *)myObject];

しかし、今日__bridge、プログラムの 1 つで誤ってメソッド呼び出しを落としてしまい、コードがコンパイルされ、問題なく実行されました。上記__bridgeのサンプルの は不要のようです。

[UIView beginAnimations:nil context:(void *)myObject];  // COMPILED OK

これは正しいですか?この場合、 は__bridge本当に不要ですか? またはそれを削除すると、コードの意味が変わりますか?

4

2 に答える 2

6

これはARC ドキュメント セクション 3.3.3 (強調鉱山) で説明されています。

3.3.3 特定のコンテキストでの保持可能オブジェクト ポインタ型からの変換

[Apple 4.0 以降、LLVM 3.1]

保持可能なオブジェクト ポインター型の式が C の保持可能なポインター型に明示的にキャストされている場合、結果がすぐに使用されない限り、プログラムは上記のように不適切な形式になります。

  • パラメータがcf_consumed属性でマークされていないObjective-Cメッセージ送信でパラメータを初期化する、または
  • パラメータが cf_consumed 属性でマークされていない、監査対象関数への直接呼び出しでパラメータを初期化します。

コードでmyObjectは、「保持可能なオブジェクト ポインター」です。「C の保持可能なポインター型」インクルードvoid*(これは、Core Foundation の「オブジェクト」がしばしばvoid*.

したがって、ObjC オブジェクトはvoid*、メソッド パラメーターとして使用された場合に暗黙的に に変換できます。その場合、追加のメモリ管理セマンティクスはありません (つまり、__bridgeキャストと同等です)。セクション 7.8では、将来このように扱われない可能性があると警告してvoid*いますが、私はそれについて心配する必要はありません。その場合、 を追加するの__bridgeは簡単です。

心に留めておくべき 1 つのことは、myObjectここでは保護されていないということです。アニメーションが完了するまで他の方法で保持するかどうかはあなた次第です。そうしないと、クラッシュする可能性があります。

于 2014-01-26T17:21:16.290 に答える
2

__bridgeC apiからobjective-Cへ、またはobjective-CからAPIへの変数/参照の所有権(保持カウントなど)を渡すために使用されます。

Clang のドキュメントを参照してください:

ブリッジキャスト

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

(__bridge T) op casts the operand to the destination type T. If T is a retainable object pointer type, then op must have a

保持不可能なポインター型。T が保持不可能なポインター型である場合、 op は保持可能なオブジェクト ポインター型を持たなければなりません。そうしないと、キャストの形式が正しくありません。所有権の譲渡はなく、ARC は保持操作を挿入しません。(__bridge_retained T) op は、保持可能なオブジェクト ポインター型である必要があるオペランドを、保持不可能なポインター型である必要がある宛先の型にキャストします。ARC はローカル値の通常の最適化に従って値を保持し、受信者はその +1 のバランスをとる責任があります。(__bridge_transfer T) op は、保持不可能なポインター型である必要があるオペランドを、保持可能なオブジェクト ポインター型である必要がある宛先の型にキャストします。ARC は、ローカル値の通常の最適化に従って、囲んでいる完全な式の最後で値を解放します。

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

__bridge_retained または __bridge_transfer キャストを純粋に使用して、ARC にそれぞれ不均衡な保持または解放を発行させることは、不適切な形式です。

今、

ボイド * t = (ボイド *) 自己; // エラー: Cast of ... requires a bridged cast なぜ間違っているのですか。なぜなら、Objective-C から C に参照をキャストしようとしているからです。参照の所有権を渡すことができませんでした。

void *t = (__bridge void *)self; // 正しい なぜそれが正しいのは、Objective-C の参照を C に転送するためです。LLVM のドキュメントによると。上記のキャスト規則を参照してください。

MyClass *myObject = [[MyClass alloc] init];
[UIView beginAnimations:nil context:(__bridge void *)myObject];

代わりにC参照型コンテキストを渡すため、上記の行はまだ完全に問題ありませんNULL

于 2014-01-26T11:42:17.660 に答える