web-dev-qa-db-ja.com

リリース、Dealloc、および自己参照

だから私はこれらすべての質問をすべて理解したと思った。それから突然、私は理解できないエラー(クラッシュ)を受け取ります。次に、クラッシュを修正するための調査を行った後、これらの重要な領域について知っていると思っていたすべてがやや間違っていることに気付きました。

以下は、誰かが答えてくれることを期待して、私がそこに投げかける8つの質問です。これらの答えは、私の理解を軌道に戻すのに大いに役立ちます。よろしくお願いします!

Q1)その参照がnilの場合、オブジェクトに対してReleaseを呼び出しても大丈夫ですか?これは無害なはずですよね?

Q2)その参照が解放され、参照カウントが0の場合、オブジェクトに対してReleaseを呼び出しても大丈夫ですか?

Q3)リリース後にnilへの参照を設定する必要がありますか? nilに設定しないとどうなりますか?

Q4)nilとNULLには本当に違いがありますか、それとも、読者/開発者がオブジェクトタイプを一瞥するだけでそれを知るのに役立つ意味的なものですか?

Q5)プロパティの使用「自己」ポインタの使用が必要ですか?

Q6)インスタンス変数を使用するには、「Self」ポインタを使用しない必要がありますか?

Q7)プロパティの代わりにインスタンス変数を使用したいのはいつですか?値型データ型のメンバーは、リリースも保持もしていないので大丈夫だと思います。

Q8)dealloc関数内からオブジェクトのdeallocを呼び出す必要がありますか?多くの例で、Releaseが呼び出されているのを見ましたが、Deallocは呼び出されていません-そのようなチュートリアルは正しくありませんか?

33
Edward An

A1)[nil release]は問題ありません(何もしません)

A2)いいえ。割り当てが解除された後はオブジェクトに触れないでください。リリース後はnilに設定する必要があります。

A3)リリースされたポインタをnilに設定する必要はありませんが、ダングリングポインタが表示されます(つまり、オブジェクトが有効かどうかはわかりません)。プロパティをnilに設定すると、基になるivarが解放されることがよくあるため、これを行わないとメモリリークが発生する可能性があります。

A4)nilとNULLは両方ともゼロなので、技術的には同じです。

A5)はい、プロパティにはself.somePropertyを使用する必要があります。これは、単なるメソッドの場合に[self someProperty]を使用する場合と同じです。

A6)selfは本質的に構造体であるため、次のようにivarにアクセスできます:self->someIvar。ただし、その必要はありません。

A7)何らかの理由でsetter/getterメソッドを実行したくない場合。セッターがnil値を許可しない場合に時々使用し、変数を解放する必要があります

A8)リリースが正しい回数呼び出されると、deallocが自動的に呼び出されます。直接deallocを呼び出さないでください([スーパーdealloc]を除く)

19
Tom Dalling

あなたはおそらくこの質問を複数の異なる質問に分割するべきでしたが、私は噛みます。

  1. はい、nilに送信されるメッセージはすべて無効です。
  2. いいえ。ref-countが0のオブジェクトは破棄されたか、間もなく破棄され、メッセージが送信されるとクラッシュするか、せいぜい例外が発生します。
  3. 状況によります。 -deallocでリリースする場合は、おそらくそうではありません。それが特定のメソッドにスコープされているオブジェクトである場合、おそらくそうではありません。再利用されるのがivarの場合は、「はい」と言います。最初の2つのケースでは、ポインターをnilに設定しないと何も起こりません。これは、通常、これらのポインターにアクセスできなくなるためです。ただし、最後のケースでは、割り当て解除されたメモリを指しているポインタにアクセスできます。メッセージを送信したり、逆参照しようとすると、アプリがクラッシュします。
  4. これらは両方とも0に等しいです。慣例により、オブジェクトポインタにはnilが使用され、その他のポインタにはNULLが使用されますが、それらを混在させても問題は発生しません。
  5. プロパティgetter/setterを呼び出したい場合は、はい。直接カプセル化するivarにアクセスしたい場合(珍しい)、いいえ。
  6. いいえ、構文self->ivarを使用してインスタンス変数にアクセスできます。実際、ivarだけを入力すると、コンパイラーは暗黙的にself->逆参照を追加します。
  7. ここで何を意味するのかわかりません。
  8. -deallocを呼び出す必要があるのは、独自の[super dealloc];メソッドで-deallocを呼び出すときだけです。その他のオブジェクトについては、常に-releaseを呼び出す必要があります。
11
kperryua

他の人は1-6で適切に答えました。

(7)Apple initとdeallocの両方でインスタンス変数を直接使用することをお勧めします。これは主に、オブジェクト(特にサブクラス化されている場合)がこれらの両方のメソッドで部分的にしか設定されていないためです。 、したがって、セッター/ゲッターを呼び出すと、些細なアクション以外の場合、誤った動作が発生する可能性があります。通常、オブジェクト内で(ゲッターを介してではなく)直接ivarに安全にアクセスでき、そうする方がわずかに効率的です。 (iPhoneでのみ関連します。)通常、すべての場合にセッターを使用する必要があります。特に、オブジェクトがサブクラス化されている場合や、他のユーザーがプロパティを監視している場合はそうです。

(8)決してdeallocを呼び出さないでください(deallocメソッド内から[superdealloc]を除く)。別のオブジェクトの所有権を持っている場合は、その所有権を放棄する必要があります(releaseまたはautoreleaseを呼び出すことによって)。次に、必要に応じて、システムはオブジェクトに対してdeallocを呼び出します。しかし、deallocを自分で呼び出すことはありません。 メモリ管理ルール を読んでください(9段落しかないため、理解することが重要です)。

8
Peter N Lewis

OK。 Bをnilに設定しないことでうまくいくことを確認しました。だから、今、私はBコントローラーを作成するとき(私がそれにナビゲートしたいとき)にnilをチェックしません。

代わりに、Bを解放してから、コントローラーを作成してBに割り当てます。次に、AのviewDidAppearメソッドで、Bを解放します。

このスレッドは現在閉じられていると思います。ありがとう!

0
Edward An

A4)種類が異なります。それらはすべてゼロですが、NULLはvoid *、nilはid、Nilはクラスポインタです。

0
Subrat Tripathy