2009-05-16 12 views
12

どちらが正しいですか?この:メモリ管理とperformSelectorInBackground:

NSArray* foo = [[NSArray alloc] initWithObjects:@"a", @"b", nil]; 
[bar performSelectorInBackground:@selector(baz:) withObject:foo]; 

- (void)baz:(NSArray*)foo { 
    ... 
    [foo release]; 
} 

または:

NSArray* foo = [[[NSArray alloc] initWithObjects:@"a", @"b", nil] autorelease]; 
[bar performSelectorInBackground:@selector(baz:) withObject:foo]; 

- (void)baz:(NSArray*)foo { 
    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; 
    ... 
    [pool release]; 
} 

私は最初のものは作品を知っているが、クランはそれについて不平を言うので、使用するより良いパターンがありますかしら。

答えて

24

まず間違っている...

私は第二1「を、単に試してみる」だろうが、自動解放して、誰がEXC_BAD_ACCESSの欠如は、あなたが右のそれをやっていることを意味するかどうかを知っているか、あなただけの幸運こと。

performSelectorInBackground:withObject:タスクが実行されるまで、barとfooの両方を保持します。したがって、あなたがそれを作成し、performSelectorInBackground:withObjectが残りを処理するようにするときは、fooを自動解放するべきです。 documentation

あなたが作成するときにあなたが自動リリースするので、後者が正しいです。 bazの中で作成するAutoreleaseプールは、fooのメモリ管理の正確さとは何の関係もありません。 autoreleaseプールがautoreleasedオブジェクトのために必要ですプール割り当てとリリースはbazで、fooの保持カウントには全く触れません。

+1

ああ、それはマニュアルにすぐそこです!愚かな私。 :) – lawrence

+4

私は明確にする必要があります:あなたは何もautoreleaseメソッドがそこに送られることを知らない限り、-baz:の内部に自動解放プールを作成して排水しなければなりません。経験則の最も良い方法は、例2のように自動解放プールを作成して作成することを想定することです。しかし[プール解放]ではなく[プールドレイン]を使用してください。 –

+0

Jim Dovey氏によると、主に主機能と同じように自動解放プールを作成する必要があります(「スレッドプログラミングガイド」を参照)。このプールはfooのautoreleaseとはまったく関係がないことを理解することは重要です。 –

2

正しいアプローチは、今、実際に行うには、次のようになります。

NSArray* foo = [[[NSArray alloc] initWithObjects:@"a", @"b", nil] autorelease]; 
[bar performSelectorInBackground:@selector(baz:) withObject:foo]; 

- (void)baz:(NSArray*)foo { 
    @autoreleasepool { 
     ... 
    } 
}