自動解放プールブロックの使用


Autorelease (自動開放) プールブロックは、オブジェクトの所有権をそれで放棄できますが、メソッドからオブジェクトを返すなどのように、すぐに割り当て解除する可能性を回避するためのメカニズムを提供します。通常は、独自の自動解放プールブロックを作成する必要はありませんが、そうする必要がある場合や、有益な場合があります。


自動開放プールブロックについて


以下の例に示すように、自動解放プールブロックには @autoreleasepool を使用してマークを付けます。


@autoreleasepool {
    // Code that creates autoreleased objects.
}

自動解放プールブロックの最後に、ブロック内で autorelease メッセージを受信したオブジェクトに release メッセージが送信されます。オブジェクトは、ブロック内で autorelease メッセージが送信されるたびに release メッセージを受信します。


他のコードブロックと同様に、autoreleaser プールブロックは入れ子にすることができます:


@autoreleasepool {
    // . . .
    @autoreleasepool {
        // . . .
    }
    . . .
}


(通常は、上記のようにコードはまったく表示されません。あるソースファイル内の autorelease プールブロック内のコードは、別の autorelease プールブロックに含まれる別のソースファイル内のコードを呼び出します)。特定の autorelease メッセージの場合、autorelease メッセージが送信された autorelease プールブロックの最後に、対応する release メッセージが送信されます。


Cocoa は、autorelease プールブロック内でコードが実行されることを常に期待しています。そうしないと、自動解放されたオブジェクトは解放されず、アプリケーションはメモリをリークします。(autorelease プールブロックの外で autorelease メッセージを送信すると、Cocoa は適切なエラーメッセージを記録します)。AppKit および UIKit フレームワークは、autorelease プールブロック内の各イベントループ反復処理 (マウスダウンイベントやタップなど) を処理します。したがって、あなたは通常、autorelease プールブロックを自分で作成する必要はなく、作成するコードを参照する必要もありません。しかし、あなた自身の autprelease プールブロックを使うかもしれない 3 つの機会があります:



ローカルの自動開放プールブロックを使用しピークメモリ使用量を削減


多くのプログラムは、自動解放される一時オブジェクトを作成します。これらのオブジェクトは、ブロックの最後までプログラムメモリの使用量に追加されます。多くの状況では、現在のイベントループの終了が過度のオーバーヘッドにならないように一時オブジェクトを蓄積できるようにします。ただし、状況によっては、一時的なオブジェクトが多数作成し、メモリの使用量に実質的に追加し、より迅速に廃棄したい場合があります。後者の場合は、独自の自動解放プールブロックを作成できます。ブロックの終わりに、一時オブジェクトが解放され、その結果通常は割り当てが解除され、プログラムメモリの使用量が削減されます。


以下の例は、for ループでローカルの autorelease プールブロックを使用する方法を示しています。


NSArray *urls = <# An array of file URLs #>
for (NSURL *url in urls) {
 
    @autoreleasepool {
        NSError *error;
        NSString *fileContents = [NSString stringWithContentsOfURL:url
                                         encoding:NSUTF8StringEncoding error:&error];
        /* Process the string, creating and autoreleasing more objects. */
    }
}


for ループは、一度に 1 つのファイルを処理します。autorelease プールブロック内の autorelease メッセージを送信したオブジェクト (fileContents など) は、ブロックの最後に解放されます。


自動解放プールブロックの後、ブロック内で自動解放されたオブジェクトを "廃棄済み" とみなす必要があります。そのオブジェクトにメッセージを送信したり、メソッドの呼び出し元に戻したりしないでください。autorelease プールブロックを超えて一時オブジェクトを使用しなければならない場合は、ブロック内のオブジェクトに retain メッセージを送信し、ブロックの後に autorelease を送信して行うことができます。以下の例を参照の事。


– (id)findMatchingObject:(id)anObject {
 
    id match;
    while (match == nil) {
        @autoreleasepool {
 
            /* Do a search that creates a lot of temporary objects. */
            match = [self expensiveSearchForObject:anObject];
 
            if (match != nil) {
                [match retain]; /* Keep match around. */
            }
        }
    }
 
    return [match autorelease];   /* Let match go and return it. */
}


autorelease プールブロック内で matchretain を送信すると、autorelease プールブロックが match の寿命を延長した後に autorelease を送信し、ループの外のメッセージを受信して findMatchingObject: の呼び出し側に返すことができます。


自動解放プールブロックとスレッド


Cocoa アプリケーション内の各スレッドは、独自の自動解放プールブロックのスタックを維持します。Foundation だけのプログラムを書いている場合、またはスレッドを切り離す場合は、独自の自動解放プールブロックを作成する必要があります。


あなたのアプリケーションやスレッドが長期間存続し、潜在的に自動解放されたオブジェクト多くを生成する場合は、自動開放プールブロック (メインスレッド上で AppKit や UIKit などがするようにう) を使用する必要があります。それ以外の場合は、自動解放されたオブジェクトは蓄積し、メモリ使用量が増加します。切り離されたスレッドが Cocoa を呼び出さない場合は、自動解放プールブロックを使用する必要はありません。


注意: NSThread の代わりに POSIX スレッド API を使用して二次スレッドを作成する場合、Cocoa がマルチスレッドモードでない限り、Cocoa を使用することはできません。Cocoaは、最初 NSThread オブジェクトを切り離した後にのみ、マルチスレッドモードに入ります。二次 POSIX スレッドで Cocoa を使用するには、アプリケーションで最初に少なくとも 1 つの NSThread オブジェクトを切り離す必要があり、このオブジェクトはすぐに終了できます。NSThread クラスメソッドで isMultiThreaded を使用して、Cocoa がマルチスレッドモードになっているかどうかをテストできます。


前の章 次の章



目次
Xcode 10 の新機能

  • メモリ管理について
  • 一目見て
    メモリー関連の問題を防ぐ良い方法
    分析ツールを使用してメモリの問題をデバッグ
  • メモリ管理ポリシー
  • 基本的なメモリ管理規則
  • オブジェクトの所有権を放棄するため dealloc の実装
    Core Foundation は、類似するが違う規則を使用
  • 実践的なメモリ管理
  • アクセッサメソッドを使用してメモリ管理を容易に
  • 弱い参照を使用して循環保持を避ける
    使用中のオブジェクトの割り当て解除を避ける
    dealloc を使って希少リソースを管理しない
    コレクションに含まれるオブジェクトを所有
    保持カウントを使用して所有権ポリシーの実装
  • 自動解放プールブロックの使用
  • 自動開放プールブロックについて
    ローカルの自動開放プールブロックを使用しピークメモリ使用量を削減
    自動解放プールブロックとスレッド
  • 文書改訂履歴












  • トップへ(Core Foundation)












    トップへ(Core Foundation)












    トップへ(Core Foundation)












    トップへ(Core Foundation)












    トップへ(Core Foundation)












    トップへ(Core Foundation)












    トップへ(Core Foundation)












    トップへ(Core Foundation)












    トップへ(Core Foundation)












    トップへ(Core Foundation)












    トップへ(Core Foundation)












    トップへ(Core Foundation)












    トップへ(Core Foundation)












    トップへ(Core Foundation)












    トップへ(Core Foundation)












    トップへ(Core Foundation)












    トップへ(Core Foundation)












    トップへ(Core Foundation)












    トップへ(Core Foundation)












    トップへ(Core Foundation)












    トップへ(Core Foundation)












    トップへ(Core Foundation)












    トップへ(Core Foundation)












    トップへ(Core Foundation)












    トップへ(Core Foundation)












    トップへ(Core Foundation)












    トップへ(Core Foundation)












    トップへ(Core Foundation)