4

Objective-cには、次のような変数を宣言する非常に簡単な方法があることを私は知っています。

NSArray* myArray;

@property(retain) NSArray* myArray;

@synthesize myArray;

このようにして、変数を保持しながら、self.myArrayをセッターとゲッターの両方として使用できます。ただし、これにより、もう1つ実行できるようになります。これは、deallocの使用を回避することです。私が理解している限り、この2つの行は同じです。

self.myArray = nil;
[myArray release];

私の質問は、どちらが好ましい方法ですか?一方が機能し、もう一方が機能しない場合はありますか?

編集:申し訳ありませんが、私はリリースを意味し、deallocではありません...

4

4 に答える 4

4

自分でdeallocを呼び出さないでください(非常に非正統的な状況を除く)。

Deallocの代わりに、呼び出し[myArray release]て、リリースされたプロセスにこれを処理させる必要があります。

ここで、 deallocメソッドについてもおそらく必要な情報よりも多くの情報を確認してください。

于 2010-12-31T23:01:48.823 に答える
3

下部の更新。

合成されたプロパティを操作(保持)する場合、deallocの役割を実行する最良の方法は、プロパティをnilに設定することです。これが「最良の」方法であると私が言う理由は、それが財産宣言によって暗示されるすべての契約が確実に満たされるようにするためです。たとえば、プロパティがアトミックであると宣言された場合(特に非アトミックであると宣言しない限り)、deallocでのこのプロパティの設定解除が同じアトミック保証で行われることを保証する唯一の方法は、 Deallocのプロパティ。また、オブジェクトのKey-Valueオブザベーションに関して正しく動作することも意味します。これは、Cocoaバインディングを使用する場合に特に重要になる可能性があります。

対応するプロパティのない(おそらくプライベートな)インスタンス変数に対して独自のメモリ管理を行う場合、いくつかのイディオムがあります。最も単純ですが、最も危険なのは、次のようにiVarをリリースすることです。

- (void)dealloc
{
    [myArray release];

    [super dealloc];
}

これにより、iVarの保持が解放されますが、他の人が述べたように、現在は古くなっている可能性のあるポインターが、誤って存在する可能性のあるオブジェクトを指している可能性のある古くなったポインターまたは保持されていないポインターによってアクセスされる可能性があります。割り当て解除。次は、別の回答で提案されているイディオムです。

- (void)dealloc
{
    [myArray release], myArray = nil;

    [super dealloc];
}

このためのさらに安全な、より衒学的なイディオムは次のとおりです。

- (void)dealloc
{
    id temp = myArray;
    myArray = nil;
    [temp release];

    [super dealloc];
}

これにより、ポイントされたオブジェクトを解放する前にiVarをクリアすることにより、ポインターの読み取りが古くなる可能性がさらに制限されます。ただし、命令の並べ替えの可能性があるため、これでもすべてのアーキテクチャでの古い読み取りに対する100%の保証ではありません。

並行性とメモリ管理のトピックについてはまだまだ多くのことが言えますが、一般に、@ synthesizedプロパティセッターがある場合は、それをdeallocで使用する必要があります。そうすることは、@ propertyの動作を変更した場合、deallocの動作が@property宣言に関して自動的に正しくなることを意味します。

重要な注意:アトミックプロパティの使用!=スレッドセーフ。(実際、私に尋ねると、原子特性は無駄ですが...)詳細については、ここを参照してください。

アップデート

これは最近再び賛成され、合成された保持プロパティを使用したアトミック保証についてここで述べたことを支持し、元の回答の他のコンテンツはそれ自体で価値がありますが、反対側に伝える必要があると感じています物語。Dave DeLongはコメントでこれのいくつかをほのめかしました、しかし私はそれが主な答えに詳細を加える価値があるだろうと思いました。

アトミック性の保証を維持する唯一の方法はnil、セッターを介してプロパティを設定することです。しかし、気にする必要はありません。理由は次のとおりです。オブジェクトがdealloc編集されている場合、それは(オブジェクトグラフが正しい場合)そのオブジェクトへの生きた参照があってはならないことを意味します。オブジェクトへの生きた参照がない場合、プロパティをクリアする操作の原子性の保証を気にすることはできません。

セッターを使用する理由として、元の回答でKVOについても言及しましたが、deallocDaveDeLongはコメントで対位法としてKVOについて言及しました。彼は正しいです。その理由は次のとおりです。オブジェクトがdealloc編集されている場合、すべてのKVOオブザーバーはすでにそのオブジェクトから削除されているはずです(ここでも、KVOであるかどうかに関係なく、生きている参照はありません)。実際、そうでない場合は、観測が行われたままオブジェクトが消えたことを通知するコンソールメッセージが表示されるまで長くはかかりません。

要するに、で合成されたセッターと同等の原子性の保証をすることはできませんがdealloc、それは決して重要ではありません(もしそうなら、何か他のものが壊れています)。

于 2010-12-31T23:29:35.473 に答える
1

オブジェクトであるインスタンス変数がある場合は常に、deallocメソッドでそれを解放する必要があります。だからあなたの場合は使用する必要があります

- (void)dealloc
{
    [myArray release], myArray = nil;

    [super dealloc];
}
于 2010-12-31T22:34:25.737 に答える
1

理論的にはnilに設定すると、ivarを解放するのと同じ効果があります。ただし、deallocメソッドを直接呼び出さないでください。Deallocメソッドでは、Davidが言及したイディオムが表示されることがあります。具体的には次のとおりです。

[myArray release], myArray = nil;

これは、deallocが完了する前に、リリースされたオブジェクトに誰かがアクセスしようとする可能性が非常に低い競合状態を回避するためです。プロパティをnilに割り当てることにより、試行されたアクセスが正常に失敗するようになります。

于 2010-12-31T23:10:38.583 に答える