3

私は現在、Apressの「BeginningiPhone3Development」に取り組んでいます。サンプルアプリケーションで使用する標準は、次のコードのようなものです。

- (void)viewDidLoad {
    BlueViewController *blueController = [[BlueViewController alloc] 
                                         initWithNibName:@"BlueView" bundle:nil];
    self.blueViewController = blueController;
    [self.view insertSubview:blueController.view atIndex:0];
    [blueController release];
}

8.14.11 UPDATE(追加情報)
blueViewControllerは次のように宣言されています。

@property (retain, nonatomic) BlueViewController *blueViewController;

彼らが実行するときはいつでも、alloc彼らはそれを一時変数(ここblueController)に入れ、それを割り当て、そしてそれを解放します。この一時変数は私には不必要に思えます。
次のようにコードを簡略化しました。

- (void)viewDidLoad {
    self.blueViewController = [[BlueViewController alloc] 
                              initWithNibName:@"BlueView" bundle:nil];
    [self.view insertSubview:blueViewController.view atIndex:0];
}

- (void)dealloc {
    [blueViewController release];
    [super dealloc];
}

私の変更したコードは、iPhoneシミュレーターでもまったく同じように実行されました。今、私はあなたが何かを割り当てるならあなたはそれを解放する必要があるという規則を知っています。そして、私は私のdealloc方法でそれをカバーしています。しかし、(が呼び出されViewDidLoadた関数)に直接リリースを含めることにはいくつかの利点がありますか?allocまたは、このようなメソッドにを含めることも同様に問題ありreleaseませdeallocんか?
助けてくれてありがとう、
-j

4

3 に答える 3

8

blueViewControllerretainプロパティであると仮定すると、一時変数は不必要ではありません。あなたの単純化はメモリリークを引き起こしています。2 番目のスニペットからの次のステートメントが漏れています。

self.blueViewController = [[BlueViewController alloc] 
                          initWithNibName:@"BlueView" bundle:nil];

所有権に関しては、alloc-init によって返されたオブジェクトを所有しているのに、プロパティ アクセサーがオブジェクトの所有権を再度主張するため、オブジェクトがover-retain されます。

一時変数を使用すると、この問題が解決します。別のオプションは、次を使用することautoreleaseです。

self.blueViewController = [[[BlueViewController alloc] 
                          initWithNibName:@"BlueView" bundle:nil] autorelease];

このステートメントの後、オブジェクトを実質的に所有し、dealloc で解放する必要があることに注意してください。


blueViewControllerプロパティの宣言方法については言及していません。とにかく、セッターのセマンティクスが ( retain, copy, assign) であっても、そのステートメントは間違っています。最も可能性の高いシナリオについては既に説明しましたretain。他の 2 つの可能性を見てみましょう (意味があるかどうかは考慮せずに)。

  • blueViewControllerたまたまプロパティだった場合copy、ステートメントもリークします。プロパティ アクセサーは元のオブジェクトをコピーし、プロパティはコピーへのポインターを保持するようになり、元のオブジェクトを追跡できなくなり、すぐにリークが発生します。

  • 最も可能性が低いシナリオは、これが間違っている可能性が最も高く、本当に必要なため、それblueViewControllerがプロパティであるということです。しかし、とにかく、プロパティはあなたが所有していないオブジェクト(デリゲートなど) のためのものであり、それらを解放することは想定されていません。所有しているオブジェクトを割り当てているため、リークするか、割り当てプロパティを誤って解放します。assignretainassign

于 2011-08-12T15:35:12.263 に答える
3
@property (retain) MyCLass *obj;

MyClass *tmpObj = [[MyClass alloc] init];
self.obj = tmpObj;
[tmpObj release];

最初の行で、 を介して一度所有権を取得しallocます。次に、2行目で、プロパティが保持されるため、再び所有権を取得します。3 行目では、 経由で取得した所有権を解放しますalloc。これで、保持プロパティを介して単一の所有権が得られ、将来リリースされる可能性がありますdealloc

を削除するとどうなるかを考えてみましょうtmpObj

self.obj = [[MyClass alloc] init];

この行では、所有権を 2 回取得します。1 回はプロパティを介してalloc、もう 1 回はプロパティを介して取得します。今[obj release]一度では十分ではありません。リークを回避するには、2 回リリースする必要があります。当然、2 回リリースすることは非常に悪いことであり、さらなるメモリ リークの原因となる可能性があります。別の呼び出しを行うとself.obj = anotherObj、古いものをリークしています。これを回避するには、この一時ポインターが必要です。

于 2011-08-12T15:38:04.403 に答える
0

頭のてっぺんから思いつく理由は 2 つあります。1 つ目は、より具体的な例ですが、が割り当てられて初期化され、実際にの ivarblueControllerに割り当てられる前に有効性がテストされる同様のメソッドがよく見られます。selfこのようなすべてのメソッドでこのパターンに従うと、オブジェクトの作成と割り当ての間のテストが容易になります。私の知る限り、そのような仲介が実際に不必要なままである場合、コンパイラはそれを最適化する必要があります。

Cocoa 内でのこのパターンの 2 番目のより一般的な目的は、単純に、Obj-C と Cocoa がメソッドと変数の非常に長くて冗長な名前を推奨することです。メソッド呼び出しを他のメソッドの直接引数として使用すると、すぐに判読できなくなる可能性があるため、慣例では、メソッドの各引数を事前に設定し、それらを中間変数に配置してから、変数を引数として使用して読みやすくし、変更を容易にすることをお勧めしますネストされたメソッド呼び出しを掘り下げる必要のない単一の引数。

于 2011-08-12T15:34:04.283 に答える