Swiftプログラムでautoreleasepoolを使用する必要はありますか?


95

このWWDC14プレゼンテーションの 17ページで、

Objective-Cを使用していますか?まだ自動解放プールを管理する必要があります
autoreleasepool {/ * code * /}

どういう意味ですか?コードベースにObjective-Cファイルautoreleasepool {}がない場合、それは不要であることを意味しますか?

関連する質問の答えは、例がありautoreleasepool便利です。

- (void)useALoadOfNumbers {
    for (int j = 0; j < 10000; ++j) {
        @autoreleasepool {
            for (int i = 0; i < 10000; ++i) {
                NSNumber *number = [NSNumber numberWithInt:(i+j)];
                NSLog(@"number = %p", number);
            }
        }
    }
}

上記のコードがautoreleasepoolドロップされてSwiftに変換された場合、Swift numberは最初に変数を解放する必要があることを認識できるほど賢くなります}か(他のいくつかの言語のように)。


1
autoreleasepoolSwiftにはドキュメントがないようです。私はあなたの質問拡大し、開発者フォーラムで質問しました
アーロンブラジャー、2014

回答:


197

autoreleasepool返すときのパターンは、スウィフトに使用されているautorelease(あなたのObjective-CのコードやCocoaクラスを使用してのいずれかで作成された)オブジェクトを。autoreleaseSwift のパターンは、Objective-Cと同じように機能します。たとえば、次のメソッドのSwiftレンディション(インスタンス化NSImage/ UIImageオブジェクト)を考えてみます。

func useManyImages() {
    let filename = pathForResourceInBundle

    for _ in 0 ..< 5 {
        autoreleasepool {
            for _ in 0 ..< 1000 {
                let image = NSImage(contentsOfFile: filename)
            }
        }
    }
}

これをInstrumentsで実行すると、次のような割り当てグラフが表示されます。

autoreleasepool

しかし、自動解放プールなしで実行すると、ピーク時のメモリ使用量が高くなることがわかります。

自動解放プールなし

autoreleasepool使用すると、Objective-Cの場合と同じように、Swiftで自動解放オブジェクトの割り当てをいつ解除するかを明示的に管理できます。

注:Swiftネイティブオブジェクトを処理する場合、通常は自動解放オブジェクトを受け取りません。これが、「Objective-Cで作業する」ときにのみ必要であるという警告がプレゼンテーションで述べられた理由ですが、Appleがこの点についてもっと明確になってほしいと思います。ただし、Objective-Cオブジェクト(Cocoaクラスを含む)を処理している場合、それらは自動解放オブジェクトである可能性があります。その場合、Objective-C @autoreleasepoolパターンのこのSwiftレンディションは依然として役立ちます。


2
これらすべての質問で、独自のクラスを作成printlndeinit、それをin にさせることができます。これにより、オブジェクトが割り当て解除されたときを正確に確認することが非常に簡単になります。またはInstrumentsで観察します。あなたの質問への回答では、Swiftオブジェクトは+1保持カウント(自動解放オブジェクトではない)を持つ関数から返され、呼び出し元はそのポイントからシームレスに所有権を管理します(たとえば、返されたオブジェクトがスコープから外れた場合、自動解放プールではなく、すぐに割り当て解除されます)。
Rob

3
@StevenHernandez自動解放プールはリークとはほとんど関係がありません。リークは、解放されていないオブジェクトが原因です。一方、自動解放プールは、プールが空になるまで解放が延期されるオブジェクトのコレクションです。プールは、何かが割り当て解除されるかどうかを制御するのではなく、単にそのような割り当て解除のタイミングを制御します。マップビューについては、キャッシュを制御することはできません(メモリを使用しますが、実際のリークではありません)。実際にリークが発生した場合は何も実行できません(また、これまでに重大なマップビューのリークは確認されていません。 UIKitでのランダムで穏やかなリーク)。
Rob

2
@mattええ、私は同様の行動を見ました。したがって、私はNSImage/ UIImageオブジェクトを使用して練習を繰り返し、問題をより一貫して明らかにしました(そして率直に言って、これは問題のより一般的な例です。これは、多くの場合、大きなオブジェクトを処理するときにピークメモリ使用量が問題になるだけなので、これの実際的な例は一連の画像のサイズを変更するルーチン)。自動解放オブジェクトを明示的に作成したObjective-Cコードを呼び出す動作も再現しました。誤解しないでください。Swiftでは自動解放プールがObjective-Cよりも少ない頻度で必要だと思いますが、それでも役割を果たす必要があります。
Rob

1
うまくいく例を見つけました!NSBundleをpathForResource:ofType:繰り返し呼び出すだけです。
2015

1
私のpathForResource:ofType:例はXcode 6.3 / Swift 1.2では動作しません。:)
マット2015

4

同等のObjective-Cコードで使用する場合は、Swiftで使用します。

Swiftは、数値変数が最初の後に解放される必要があることを知るのに十分賢いでしょう}

Objective-Cの場合のみ。どちらもCocoaのメモリ管理ルールに従って動作します。

もちろん、ARC numberは、ループのその反復の終わりにスコープ外になることを知っており、それを保持している場合はそこで解放します。ただし、自動解放されたインスタンスが返された場合と返され-[NSNumber numberWithInt:] なかっ場合があるため、オブジェクトが自動解放されたかどうかはわかりません。のソースにアクセスできないため、知る方法はありません-[NSNumber numberWithInt:]


1
Swiftがこの目的でObjective-Cと同じように動作する場合、プレゼンテーションで「Working with Objective-C?」と述べたのはなぜですか?具体的には?
イーサン

9
@EthanネイティブのSwiftオブジェクトは自動解放オブジェクトではないようで、autoreleasepool構成は完全に不要です。しかし、SwiftコードがObjective-Cオブジェクト(Cocoaオブジェクトを含む)を処理している場合、それらは自動解放パターンに従うため、autoreleasepool構造が役立ちます。
Rob

「autoreleasepoolを使用すると、Swiftでautoreleaseオブジェクトの割り当てをいつ解除するかを明示的に管理できます」というメッセージが表示されますが、なぜそうしたいのですか?コンパイラーがなぜそれをできない/できないのですか?VMが巨大な文字列操作のタイトなループで屋根を通り抜けないようにするには、独自の自動解放プールを追加する必要がありました。どこに追加するかは私には明らかで、完璧に機能しました。コンパイラがそれを実行できなかったのはなぜですか?コンパイラをうまく機能させるために、より賢くすることはできますか?
vonlost
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.