NSAutoreleasePoolはメソッド間で実行されますか?
-
06-07-2019 - |
質問
UIをハングさせないように、バックグラウンドで長時間実行される作業を行うためにスレッドを切り離すiPhoneアプリケーションを構築しています。スレッドには、メモリ管理のためにNSAutoreleasePoolインスタンスが必要であることを理解しています。スレッド化されたメソッドが別のメソッドを呼び出すかどうかはわかりません-そのメソッドにもNSAutoreleasePoolが必要ですか?
サンプルコード:
- (void)primaryMethod {
[self performSelectorInBackground:@selector(threadedMethod) withObject:nil];
}
- (void)threadedMethod {
NSAutoreleasePool *aPool = [[NSAutoreleasePool alloc] init];
// Some code here
[self anotherMethod];
// Maybe more code here
[aPool drain];
}
- (void)anotherMethod {
// More code here
}
私が尋ねる理由は、プールが設定されていない状態でオブジェクトが自動解放され、「リークしている」というエラーが表示されることです
他の質問で、自動解放プールがまったく設定されていなかったことがありますが、自動解放プールが必要な理由を理解しています。 (この例では) threadedMethod
で作成された自動解放プールが anotherMethod
で作成されたオブジェクトに適用されるかどうかを調べることに特に興味があります。
解決
あなたの質問に答えるために、yes、anotherMethodはthreadedMethodで作成したNSAutoreleasePoolを使用しており、aPoolがリリース/ドレーンされるとそこにあるオートリリースはすべてリリースされます。
したがって、エラーがこのコードに直接起因している可能性はほとんどありません(さらに続けられない限り)。
_NSAutoreleaseNoPoolにブレークポイントを設定し(ブレークポイントウィンドウに名前で追加)、デバッガーでコードを実行すると、プールなしで自動解放が呼び出されると停止し、問題が解決するはずです。
他のヒント
あなたの例では、はい、NSAutoreleasePoolはメソッド間で実行されます。これは、 [self anotherMethod]
の呼び出しが-(void)threadedMethod
内にネストされているためです。
- Q:メソッド間でNSAutoreleasePoolを実行しますか?
- A:依存します:
- ネストされた呼び出し間で、はい。
- 兄弟の呼び出し全体、いいえ。
そして何があっても、親スコープがなくなると、 NSAutoreleasePool
インスタンス自体がスコープから外れます。 -あなたの例では、-(void)threadedMethod {}
の最後に。
前述の記事( http://thegothicparty.com/dev/macos/nsautoreleasepool/ )それについては非常に明確です。
自動解放プールはanotherMethodに引き継がれます。ただし、スレッド関数が終了したら、[aPool drain]の代わりに[aPool release]を呼び出す必要があります。これらはほぼ同等ですが、aPoolをリリースすると、NSAutoreleasePoolがプール内の他のすべてのオブジェクトに加えて自身をリリースします。 drainを呼び出した後、スレッド関数が終了しても、自動解放プールの保持カウントはまだ+1です!オッズは、「ただ漏れている」ということです。オブジェクトはaPoolです。
編集:
Jim Pulsは、リリースとドレインが同等であることについて正しいです。 Appleのドキュメントは、ガベージコレクトされていない環境では同一であり、ガベージコレクトされた場合はドレインが優れていると明確に述べています。ドキュメントを読んでいないことの私のせい!
NSAutoreleasePoolsの一般的な概要を示す記事を次に示します。正しい方向を示すのに役立つはずです。自動解放プールの仮想スタックがあるため、オブジェクトが自動解放されている場所に関係なく、最上位のプールがアプリ内のあらゆる場所で使用されます。