web-dev-qa-db-ja.com

ARC-__unsafe_unretainedの意味?

私はそれが正しいことを確認したいだけです:

  1. 所有していない__unsafe_unretainオブジェクトは必要ですか?
  2. オブジェクトが__unsafe_unretainedの場合、@propertyassignを使用する必要がありますか?これは、オブジェクトが保持されず、単に割り当てられたオブジェクトを参照することを意味しますか?
  3. デリゲートを除いていつ使用したいですか?
  4. それはARCのものですか、それとも以前に使用されていましたか?
76
shannoga

LLVMコンパイラ3.0では、__strong__autoreleasing__unsafe_unretained、および__weakの4つの新しい所有者修飾子が導入されています。最初の3つは、ARC以外でも 仕様 に従って利用可能です。

Joshuaが示すように、デフォルトでは、すべてのポインターはARCの下で__strongであると暗示されています。つまり、オブジェクトがそのポインターに割り当てられると、そのポインターがそれを参照している限り保持されます。ほとんどの場合これで問題ありませんが、答え here で説明しているように、保持サイクルの可能性が広がります。たとえば、インスタンス変数として別のオブジェクトを含むオブジェクトがあり、その2番目のオブジェクトがデリゲートとして最初のオブジェクトに戻る強力なリンクを持っている場合、2つのオブジェクトは解放されません。

__unsafe_unretainedおよび__weak修飾子が存在するのはこのためです。それらの最も一般的な用途はデリゲートであり、weakまたはunsafe_unretained属性(assignは実質的にunsafe_unretained)でそのデリゲートのプロパティを定義します。次に、それぞれのインスタンス変数に__weakまたは__unsafe_unretainedのマークを付けて一致させます。つまり、デリゲートインスタンス変数は最初のオブジェクトを指し示しますが、そのオブジェクトが保持されることはないため、保持サイクルが中断され、両方のオブジェクトが解放されます。

デリゲートを超えて、これはあなたのコードで形成されるかもしれない他の保持サイクルを壊すのに役立ちます。リークスインストゥルメントにはサイクルビューが含まれており、アプリケーションで検出された保持サイクルがグラフィカルに表示されます。

__unsafe_unretained__weakの両方は、オブジェクトの保持を防ぎますが、わずかに異なる方法で。 __weakの場合、オブジェクトへのポインターは、それが指すオブジェクトの割り当て解除時にnilに変換されます。これは非常に安全な動作です。その名前が示すように、__unsafe_unretainedは、オブジェクトが割り当て解除された後でも、オブジェクトが存在したメモリをポイントし続けます。これにより、その割り当て解除されたオブジェクトへのアクセスが原因でクラッシュする可能性があります。

なぜ__unsafe_unretainedを使用するのですか?残念ながら、__weakは、デプロイメントターゲットとしてiOS 5.0とLionでのみサポートされています。 iOS 4.0とSnow Leopardをターゲットに戻す場合は、__unsafe_unretained修飾子を使用するか、Mike Ashの MAZeroingWeakRef のようなものを使用する必要があります。

188
Brad Larson
  1. いいえ、所有していないオブジェクトにweakを使用することもできます。
  2. いいえ、プロパティでunsafe_unretainedを使用することもできます。
  3. 私の理解では、unsafe_unretainedアイテムはweakに似ていますが、ポイントするアイテムが解放されたとき(およびそれに伴うオーバーヘッド)をクリアする追加の安全性はありません。
  4. これは完全にARCのことです。
4
dasblinkenlight

__unsafe_unretainedは、ARCの前のオブジェクトのデフォルトストレージと同じです。 ARCでは、デフォルトは__strongは、参照が範囲外になるまで、その参照を持っていることを意味します。

4
Joshua Weinberg

__unsafe_unretainedに関する別の観察:デバイス上のアプリでクラッシュが発生し、iVarsが__unsafe_unretainedとして宣言されているシミュレーターで[〜#〜] not [〜#〜]が発生しました。はい、ARC移行からのコードのバグでしたが、デバイスとシミュレーターのこのような違いに気付いたのは初めてでした。

1
Gerd