web-dev-qa-db-ja.com

didReceiveMemoryWarningの実装方法

私は単純な位置認識iPhoneアプリケーションを開発しました。このアプリケーションは、電話機の低メモリ状態を除いて、期待どおりに機能します。

携帯電話の低メモリ状態では、アプリがクラッシュします。空き容量を増やして携帯電話のメモリを増やすと、クラッシュすることなく正常に動作し始めます。

問題をグーグルで調べたとき、メモリ不足の状態では、OSがdidReceiveMemoryWarningを現在の階層のすべてのコントローラーに送信し、それぞれがdidReceiveMemoryWarningメソッドを実装し、ビューのiboutletをnilに設定することがわかりました現在表示されていません。

また、そのコントローラーのビューが表示されていない場合、nilパラメーターを指定したメソッドsetViewが呼び出され、ビューに接続されているアウトレット変数がある場合、それらを削除する際に問題が発生することをどこかで読みました。

したがって、これらすべてのFundasで、didReceiveMemoryWarningおよびviewDidUnloadメソッドを実装することにより、iPhoneによって発生した低レベルのメモリ状態を処理するのに最適なものは何ですか。

上記の問題の解決のために適切な例かリンクを可能にしてください。

ありがとう。

47
harshalb

私が投稿している1つの例...私はどこからコピーした...それはあなたにいくつかのアイデアを与えるかもしれません...

- (void)didReceiveMemoryWarning {

    // Release anything that's not essential, such as cached data (meaning
    // instance variables, and what else...?)

    // Obviously can't access local variables such as defined in method
    // loadView, so can't release them here We can set some instance variables
    // as nil, rather than call the release method on them, if we have defined
    // setters that retain nil and release their old values (such as through use
    // of @synthesize). This can be a better approach than using the release
    // method, because this prevents a variable from pointing to random remnant
    // data.  Note in contrast, that setting a variable directly (using "=" and
    // not using the setter), would result in a memory leak.
    self.myStringB = nil;
    self.myStringD = nil;
    [myStringA release];// No setter defined - must release it this way
    [myStringC release];// No setter defined - must release it this way

    /* 3. MUST CONFIRM: NOT necessary to release outlets here - See override of
       setView instead.
    self.labelA = nil;
    self.imageViewA = nil;
    self.subViewA = nil;
     */
    // Releases the view if it doesn't have a superview
    [super didReceiveMemoryWarning];
}
21
Mihir Mehta

IOS 5以前。

コントローラがメモリ警告を受信すると、didReceiveMemoryWarningが呼び出されます。その時点で、コントローラーのビューがビュー階層にない場合、ビューはnilに設定され、viewDidUnloadは自動的に呼び出されます。したがって、viewDidUnloadで行う必要があるのは、viewDidLoadで作成されたサブビューまたはNibから作成されたサブビューを解放することです。このような:

- (void)viewDidUnload
{
    self.subView = nil;
    self.subViewFromNib = nil;
}

- (void)didReceiveMemoryWarning
{
    self.someDataCanBeRecreatedEasily = nil;
    [super didReceiveMemoryWarning];
}

IOS6で。

コントローラーは、メモリ警告を受け取ったときにビューを自動的に解放しません。したがって、viewDidUnloadは呼び出されません。ただし、メモリ警告が発生した場合は、ビュー(サブビューを含む)を解放する必要があります。このような。

- (void)didReceiveMemoryWarning
{
    if ([self isViewLoaded] && [self.view window] == nil) {
        self.view = nil;
        self.subView = nil;
        self.subViewFromNib = nil;
    }
    self.someDataCanBeRecreatedEasily = nil;
    [super didReceiveMemoryWarning];
}

ビューが読み込まれる前に[セルフビュー]を呼び出さないことに注意してください。ビューがロードされていない場合、このメソッドはビューを自動的にロードします。

ビューがウィンドウに追加されていない場合にのみビューを解放できることに注意してください。

15
wihing

メモリ警告は、絶対に重要ではないリソースを破棄する必要があるというシグナルです。ほとんどのコントローラーは、多くの場合再計算を保存するために、データキャッシュ、中間データ、またはその他の断片にハングアップします。メモリ警告を受け取ったら、動作するためにすぐに必要のないものをフラッシュし始めます。

何が「重要」であるかをどのように判断するかは、アプリケーションの設計に完全に依存します。たとえば、OpenGLゲームは、現在画面に表示されているテクスチャが価値があると判断し、表示されていないテクスチャや、現在のプレイエリアの境界外にあるレベルデータをフラッシュします。広範なセッションログ(IRCクライアント)など)を使用するアプリケーションは、メモリからディスクにフラッシュする場合があります。

ご覧のように、警告は階層内の各コントローラーに送信されるため、各要素は、どのデータが「運用に不可欠」であり、「消費可能」であるかを個別に判断する必要があります。すべてを最適化してもメモリ不足の警告が表示される場合は、残念ながらハードウェアの制限を超えているため、コアアプリケーションの設計を再検討する必要があります。

15
Dan Story

didReceiveMemoryWarningで何をするかはあなた次第です。 OSはメモリが少ないことを通知しているため、できるだけ早く解放する必要があります。これは、キャッシュされたデータをすべて解放する、表示されていないビューをアンロードするなどのアイデアです。詳細はアプリケーション固有です。

5
richb

クラスの静的変数に割り当てたdidReceiveMemoryWarningのメモリを解放することもできます。静的変数のメモリが割り当てられると、アプリケーションの実行中に解放されないためです。

4
schaechtele

驚いたことに、公式のiPhoneサンプルでは、​​didReciveMemoryWarningを実装しているアプリはわずかです。 iPhoneCoreDataRecipesの例を参照として使用できます。

一部のサンプル(TableViewSuiteなど)は別のことを行います;-)

2
ohho