私が理解しているように、alloc、new、またはcopyで作成されたものはすべて手動でリリースする必要があります。例えば:
int main(void) {
NSString *string;
string = [[NSString alloc] init];
/* use the string */
[string release];
}
しかし、私の質問は、これは同じくらい有効ではないでしょうか?
int main(void) {
NSAutoreleasePool *pool;
pool = [[NSAutoreleasePool alloc] init];
NSString *string;
string = [[[NSString alloc] init] autorelease];
/* use the string */
[pool drain];
}
はい、2番目のコードスニペットは完全に有効です。
-autoreleaseがオブジェクトに送信されるたびに、最も内側の自動解放プールに追加されます。プールが空になると、プール内のすべてのオブジェクトに-releaseが送信されます。
自動解放プールは、「後で」送信するまで-releaseの送信を延期できる便利な機能です。その「後」はいくつかの場所で発生する可能性がありますが、Cocoa GUIアプリで最も一般的なのは、現在の実行ループサイクルの終わりです。
drain
とrelease
の機能は混乱を引き起こしているように見えるので、ここで明確にする価値があるかもしれません(ただし、これは ドキュメント ...でカバーされています)。
厳密に言えば、全体像から見ると、drain
はnotrelease
と同等です。
参照カウント環境では、drain
はrelease
と同じ操作を実行するため、この意味では2つは同等です。強調するために、これは、drain
ではなくrelease
を使用する場合、プールをリークnotすることを意味します。
ガベージコレクション環境では、release
はノーオペレーションです。したがって、効果はありません。一方、drain
には、「必要に応じて収集する」コレクターへのヒントが含まれています。したがって、ガベージコレクション環境では、drain
を使用すると、システムがコレクションスイープのバランスを取るのに役立ちます。
既に指摘したように、2番目のコードスニペットは正しいです。
すべての環境(参照カウント、GC、ARC)で動作し、ドレイン/リリースの混乱を回避する自動リリースプールを使用するより簡潔な方法を提案したいと思います。
int main(void) {
@autoreleasepool {
NSString *string;
string = [[[NSString alloc] init] autorelease];
/* use the string */
}
}
上記の例では、@ autoreleasepoolブロックに注意してください。これは文書化されています here 。
いや、違うよ。ドキュメントには、非GCでは-drainは-releaseと同等であり、NSAutoreleasePoolはnotがリークされることを明確に示しています。
NSAutoReleasePoolをいつ、どのように使用するかについて、このリンクが最良の説明を提供していることがわかりました。 AutoReleasePool
オブジェクトにリリースの代わりに自動リリースを送信すると、少なくともプール自体が空になるまでそのオブジェクトのライフタイムが延長されます(その後オブジェクトが保持される場合は長くなる可能性があります)。オブジェクトは同じプールに複数回配置できます。その場合、オブジェクトはプールに配置されるたびにリリースメッセージを受け取ります。
ええ、あなたのコードは完璧です。ガベージコレクションを使用している場合は、処理が完了したら文字列をnilに設定するだけで十分です。ガベージコレクションはアプリのパフォーマンスに向いていないため、使用をお勧めしません:P
Appleからの読み物:「自動解放プールブロックの最後に、ブロック内で自動解放メッセージを受信したオブジェクトに解放メッセージが送信されます。オブジェクトは、ブロック内で自動解放メッセージを送信するたびに解放メッセージを受信します。 」