オブジェクトを割り当てて初期化する次の2つの方法の違いは何ですか?
AController *tempAController = [[AController alloc] init];
self.aController = tempAController;
[tempAController release];
そして
self.aController= [[AController alloc] init];
ほとんどのAppleの例では最初のメソッドを使用しています。なぜ割り当て、初期化、オブジェクトしてからすぐに解放しますか?
すべてのオブジェクトには参照カウントがあります。 0になると、オブジェクトの割り当てが解除されます。
プロパティが@property (retain)
として宣言されたと仮定します:
最初の例、行ごと:
alloc
によって作成され、参照カウントは1です。self
の_setAController:
_メソッドに渡され、retain
メッセージを送信します(メソッドはオブジェクトの送信元を知らないため)。その参照カウントをインクリメントしますから2。release
を呼び出して、参照カウントを1に減らします。2番目の例では基本的にステップ1と2を実行しますが、3は実行しません。したがって、オブジェクトの参照カウントは2です。
ルールは、オブジェクトを作成した場合、それを使い終わったらリリースする責任があります。この例では、コードはプロパティを設定した後にtempAControllerで実行されます。そのオブジェクトを保持する必要がある場合、retain
を呼び出すのはセッターメソッドの責任です。
Objective-Cの_self.property = foo;
_は実際には_[self setProperty:foo];
_の略記であり、_setProperty:
_メソッドは必要に応じてオブジェクトを保持またはコピーすることを覚えておくことが重要です。
プロパティが@property (copy)
と宣言された場合、オブジェクトは保持される代わりにコピーされます。最初の例では、元のオブジェクトはすぐに解放されます。 2番目の例では、元のオブジェクトの参照カウントは0であっても1になります。したがって、同じ方法でコードを記述できます。
プロパティが@property (assign)
と宣言された場合、self
はオブジェクトの所有権を主張しておらず、他の誰かがそれを保持する必要があります。この場合、最初の例は正しくありません。これらの種類のプロパティはまれであり、通常はオブジェクトデリゲートにのみ使用されます。
他の人が指摘したように、表示する2つのコードスニペットは同等ではありません(メモリ管理の理由から)。前者が後者よりも選ばれる理由について:
後者の正しい定式化は
self.aController= [[[AController alloc] init] autorelease];
前者と比較して、これは自動解放プールの使用により追加のオーバーヘッドを追加し、状況によっては、オブジェクトの有効期間が不必要に延長され(自動解放プールが解放されるまで)、アプリケーションのメモリフットプリントが増加します。
他の「可能な」実装(例がどこにあるかによる)は単純です:
aController = [[AController alloc] init];
ただし、インスタンス変数を直接設定することは、initメソッドまたはdeallocメソッド以外の場所では強く推奨されません。その他の場所では、常にアクセサメソッドを使用する必要があります。
これにより、サンプルコードに示されている実装が行われます。
AController *tempAController = [[AController alloc] init];
self.aController = tempAController;
[tempAController release];
次の理由から、これはベストプラクティスに従います。
Xcodeを使用している場合、静的アナライザーでそのようなコードを検出するのに役立ちます。 [ビルド] >> [ビルドと分析]をクリックするだけです
これにより、このようなコードで非常に役立つメッセージが表示されます。
また、コードを1行にまとめたいという要望があるため、多くの人がAutoreleaseを使用していることに注意してください。
self.aController = [[[AController alloc] init] autorelease];
理論的にはiPhoneの自動リリースは多少高価であるため(理由を明確に説明することはありません)、オブジェクトを他の場所に割り当てた直後に明示的にリリースすることができます。
注意すべきもう1つの点は、例がaControllerの@property定義にも依存していることです。
@property (readwrite, retain) id aController;
として定義されている場合、サンプルは動作しますが、@property (readwrite, assign) id aController;
として定義されている場合、releaseの追加呼び出しによりオブジェクトの割り当てが解除されます。
あなたもできる
@property (nonatomic, retain)AController *aController;
...
self.aController= [[AController alloc] init];
[aController release];
保持プロパティを使用すると、同じように機能しますが、混乱を少なくするために(プロパティを保持するために)他の方法を使用する方が適切です。このコードにより、実際にaController setAControllerが保持するため、そうではありません。