5

私はちょうどCABasicAnimationfor shadowPath プロパティを設定していましたが、これは私を興味深くしました:

shadowAnimation.toValue = (id)newShadowPath.CGPath;

[注: shadowAnimation はCABasicAnimationオブジェクトでnewShadowPathあり、UIBezierPathオブジェクトです]

これは機能し、Xcode にエラーや警告は表示されません。ただし、次のように書くと:

CGPathRef test = newShadowPath.CGPath;
shadowAnimation.toValue = (id)test;

これはコンパイルされず、次の警告メッセージがスローされます。

Cast of C pointer type 'CGPathRef' (aka 'const struct CGPath *') to Objective-C pointer type 'id' requires a bridged cast

したがって、次のように入力する必要があります。

shadowAnimation.toValue = (__bridge id)test;

これはなぜですか?(id)newShadowPath.CGPathのみを使用すると、最初の例で同じエラーが発生しないのはなぜですか。? __bridgeXcodeが問題を検出していなくても、そこにキャストを配置するのは正しいでしょうか? それとも、ここで何が違うのですか?

4

2 に答える 2

2

この違いの理由は、clang 3.1 で導入された新しい (そして少し複雑な) 変換規則にあります。

まず、それを煮詰めましょう:

@@interface Foo : NSObject
+ (CGPathRef)bar;
@end

CGPathRef foo();

void test()
{
    // works without bridged cast:
    id a = (id)[Foo bar];

    // needs bridged cast
    id b = (__bridge id)foo();
}

したがって、メッセージの結果をキャストするとき、通常の関数呼び出しで必要な場合は brdge キャストを省略できます。それは奇妙に思えます。

この違いの理由は、ARC が関数とメソッド名をどのように解釈し、いわゆるC 保持可能ポインター型(Core Foundation オブジェクト) の保持カウントに関する仮定を導出するかにあります。

ARC ガイドのセクション 3.3.2 ( 「既知のセマンティクスを持つ式の保持可能なオブジェクト ポインター型への変換」) で、不一致の理由を見つけることができます。

式がC の保持可能なポインター型の右辺値であり、[...] メッセージ送信 [...] である場合、その式は保持されないことがわかっています。

キャストオペランドが保持されていないことがわかっている場合[...] 変換は __bridge キャストとして扱われます

同じセクションでは、これが C 関数に適用されない理由と、clang が同様の仮定を行えるように修飾する方法について説明しています。したがって、上記の例を変更して、C 関数呼び出しのブリッジ キャストを取り除くこともできます。

CGPathRef foo() __attribute__((cf_returns_not_retained));

最後の質問に答えるには: 両方の場所でブリッジ キャストを使用しても安全です。ARC が正しい__bridgeキャストを選択することも確認します (__bridge_transferメソッドの名前に応じてキャストを選択できます。この場合は を使用__bridgeしますが)。

于 2013-03-07T12:12:32.053 に答える
2

これは ARC と、割り当てが発生したときに ARC が行う魔法によって引き起こされます。

一時変数を作成しCGPathRef testてそれに割り当てると、ARC は、標準のメモリ パラダイムに従っていない CoreBlank インスタンスを使用していることを認識し、それを保持したり、特別なことをしたりしません。

後で、この管理されていないインスタンスを保持id型のプロパティに割り当てようとすると、LLVM はそのインスタンスのメモリを管理する必要がないと判断したため、すぐにびっくりしますが、今では開始する必要があります (これは__bridgeキーワードの意図)。

最初のコード スニペットで、それが機能する理由は、そのインスタンスを ARC 管理として扱う必要があることを ARC が常に認識しており、ARC 管理されていないインスタンスへの参照が存在しないためです。

于 2013-03-07T11:06:28.693 に答える