web-dev-qa-db-ja.com

IBOutletおよびその他に対して弱いまたは強い

プロジェクトをARCに切り替えましたが、IBOutletsにstrongweakのどちらを使用する必要があるのか​​わかりません。 Xcodeはこれを行います。たとえば、インターフェイスビルダーでUILabelを作成し、アシスタントエディターを使用してViewControllerに接続すると、次のようになります。

@property (nonatomic, strong) UILabel *aLabel;

strongを使用していますが、代わりにRayWenderlich Webサイトで次のようなチュートリアルを読んでいます。

しかし、これら2つの特定のプロパティについては、他の計画があります。 strongの代わりに、weakとして宣言します。

@property (nonatomic, weak) IBOutlet UITableView *tableView;
@property (nonatomic, weak) IBOutlet UISearchBar *searchBar;

Weakは、すべてのoutletプロパティに推奨される関係です。これらのビューオブジェクトはすでにビューコントローラのビュー階層の一部であり、他の場所に保持する必要はありません。アウトレットweakを宣言することの大きな利点は、viewDidUnloadメソッドを記述する時間を節約できることです。

現在、viewDidUnloadは次のようになっています。

- (void)viewDidUnload
{
    [super viewDidUnload];
    self.tableView = nil;
    self.searchBar = nil;
    soundEffect = nil;
}

これを次のように簡略化できます。

- (void)viewDidUnload
{
    [super viewDidUnload];
    soundEffect = nil;
}

したがって、weakの代わりにstrongを使用し、videDidUnloadでnilへの設定を削除します。代わりに、Xcodeはstrongを使用し、viewDidUnloadself... = nilを使用します。

私の質問は、いつstrongを使用する必要があるか、およびweakはいつですか? iOS 4の展開ターゲットにも使用したいので、unsafe_unretainを使用する必要があるのはいつですか? ARCでstrongweakunsafe_unretainを使用すると、誰でも簡単なチュートリアルで私をうまく説明できますか?

32
Piero

経験則

親が子オブジェクトへの参照を持っている場合、strong参照を使用する必要があります。子が親オブジェクトへの参照を持っている場合は、weak参照またはunsafe_unretained参照を使用する必要があります(前者が使用できない場合)。代表的なシナリオは、デリゲートを扱う場合です。たとえば、UITableViewDelegateは、テーブルビューを含むコントローラークラスを保持しません。

enter image description here

ここでは、主要な概念を示す簡単なスキーマを示します。

最初のA、B、Cがstrong参照であるとします。特に、Cにはその親へのstrong参照があります。 obj1が解放されると(どこか)、A参照は存在しなくなりますが、obj1とobj2の間に循環があるため、リークが発生します。保持カウント(は説明の目的でのみ)と言えば、obj1の保持カウントは2です(obj2にはstrongへの参照がありますit)、obj2の保持カウントは1ですが、obj1が解放されると、その保持カウントは1になり、deallocメソッドは呼び出されません。 obj1とobj2はまだメモリに残っていますが、それらへの参照はありません:Leak

反対に、AとBだけがstrong refsであり、Cがweakとして修飾されている場合、すべて問題ありません。漏れはありません。実際、obj1がリリースされると、obj2もリリースされます。保持カウントに関して言えば、obj1の保持カウントは1、obj2の保持カウントは1です。obj1が解放されると、その保持カウントは0になり、deallocメソッドが呼び出されます。 obj1とobj2がメモリから削除されます。

簡単な提案:ARCを扱うときは、オブジェクトグラフの観点から考え始める

最初の質問については、XIBを扱うときに両方のソリューションが有効です。一般に、weak参照は、メモリサイクルを処理するときに使用されます。 XIBsファイルに関しては、strongを使用する場合、nilviewDidUnloadに設定する必要があります。そうしないと、メモリ不足の状態で予期しないリークが発生する可能性があるためです。 ARCが代わりに行うので、deallocでそれらを解放しません。ターゲットオブジェクトが破棄されると、これらの値は自動的にweakとして設定されるため、nilはそのような処理を必要としません。ぶら下がりポインタはもうありません。

あなたが興味を持っているなら、私はあなたに本当に読むことを勧めます friday-qa-2012-04-13-nib-memory-management byMike Ash

2番目の質問について、iOS 4をサポートする必要がある場合は、weakではなくunsafe_unretainedを使用する必要があります。

SO内には、多くの質問/回答があります。主なものは次のとおりです。

ARCを使用してiOS 4.0をターゲットとする場合、弱参照をどのように置き換えるのですか?

Objective-Cの自動参照カウントはどのようなリークを防止または最小化しませんか?

ARC、ライフタイム修飾子の割り当て、およびunsafe_unretainedを使用

強い/弱い/保持/ unsafe_unretained /割り当て

お役に立てば幸いです。

更新

Shaunlimのコメントによると、iOS 6のviewDidUnloadメソッドからは非推奨です。ここで私はロブの答えを見ることを本当に提案します: iOS 6-viewDidUnloadがdidReceiveMemoryWarningに移行しますか?

69
Lorenzo B

IBOutletを介してIB内のオブジェクトに接続されているオブジェクトにウィークを使用できます。この場合、スーパービューが存在する限り、オブジェクトはそこにあるからです。これは、スーパービューにサブビューへの強いポインタがあるためです。

定義しているポインターがオブジェクトへの唯一のポインターである場合、強いものとして宣言する必要があります。

登録済みの開発者の方は、WWDC11とWWDC12のビデオをご覧になることを強くお勧めします。もう1つの優れたリソースは、 Stanford。 のiOS開発ポッドキャストです。

11
dasdom