2012-04-29 1 views
0

メインバンドルから静的プロパティリストを読み込みます。十分に簡単です。しかし、プロパティリストはnilに設定しても割り当て解除されません。どうしてこれなの?プロパティリストは膨大なので、割り当てられたメモリは簡単に監視できます。なぜこのNSArrayはARCの下で割り当て解除されませんか?

- (void)someMethodCalledOnTheMainThread 
{ 
    @autoreleasePool { 
     NSString *bundleFilePath = @"..."; 
     NSPropertyListFormat format = NSPropertyListBinaryFormat_v1_0; 
     NSError *error = nil; 
     NSArray *myArray = [NSPropertyListSerialization propertyListWithData:[NSData dataWithContentsOfFile:bundleFilePath] 
                      options:NSPropertyListImmutable 
                      format:&format 
                      error:&error]; 
    } 

} 
+0

この例では、 'NSData'の代わりに' NSInputStream'を使ってプロパティリストを読む方が良いでしょう。なぜなら、ストリームはメモリ内のファイルの一部だけを一度に必要とするからです。 – ughoavgfhw

+1

配列を作成するために使用されたNSDataではなく、割り当て解除されないのはNSArrayですか? NSDataはオートレリースされているので、メソッドを終了するか、呼び出しの回りに自動解放プールを置く必要があります。 – dasblinkenlight

答えて

2

配列が自動解放されました:自動解放プール付き

NSPropertyListFormat format = NSPropertyListBinaryFormat_v1_0; 
NSError *error = nil; 
NSArray *myArray = [NSPropertyListSerialization propertyListWithData:[NSData dataWithContentsOfFile:bundleFilePath] 
                      options:NSPropertyListImmutable 
                      format:&format 
                      error:&error]; 

myArray = nil; 
// Still takes up allocated space (as seen in memory monitor via instruments). 

memory management guidelinesによれば、propertyListWith...メソッドは、自動解放されたオブジェクトを返します。これは、将来、ある時点で解放されるオブジェクトへの参照があることを意味します。あなたのコードは、(ARCなし)基本的にはこれに相当します。

NSArray *myArray = [[NSPropertyListSerialization propertyListWith/*stuff*/] retain]; 
// 1 reference + 1 autoreleased reference 
[myArray release]; myArray = nil; 
// 1 autoreleased reference 

あなたは、配列を含む自動解放プールを排出しませんでしたので、それへの参照がまだあります。現在の実行ループが終了するか、スレッドが終了する可能性が最も高い、将来のある時点で割り当てが解除されます。より早く配列を強制的に解放したい場合は、独自の自動解放プールを作成することができます。

@autoreleasepool { 
    NSArray *myArray = [[NSPropertyListSerialization propertyListWith/*stuff*/] retain]; 
    // 1 reference + 1 autoreleased reference 
    [myArray release]; myArray = nil; 
    // 1 autoreleased reference 
} // no references. The array is deallocated 

ここで、配列は既知の時刻に解放されます。プールのスコープ内で作成された他のオートレリース済みオブジェクトもリリースされるため、計画していないと問題が発生する可能性があることに注意してください。これにより、配列の割り当てが解除されるタイミングをより明示的に制御できますが、ループ内でこのプロパティリストを作成しない限り、顕著な違いは生じません。