3

私が取り組んでいるアプリは比較的単純ですが、メモリの警告が表示されます。アプリの設計に必要なメモリが多すぎて、使用量を減らすために再設計して分割する必要があるのか​​ 、それともアプリの設計は問題ないが、アプリ自体が肥大化して必要以上のメモリを誤って飲み込んでいるのかを把握しようとしています.

アプリは一連の質問を含む XML ファイルを Web からダウンロードし、質問コントロールのリストを表示する UIScrollView を生成します。各質問コントロールには、UITextView と UISegmentedControl、UIButton、UITableView、UITextField、または UIButton (カスタム日付コントロール) を備えた 4 つの UITextField があります。スクリーンショットは次のとおりです。

http://i.imgur.com/vpa9Z.png

このセットアップは、小さな問題セットには最適ですが、120 を超える問題の大きなセットでは、アプリがメモリ警告をスローし始めます。これは、より大きなセットで割り当てと VM トラッカー インストゥルメントを使用した典型的な実行です。

http://i.imgur.com/gyWOX.png

xml のダウンロードとモデルの読み込み時に割り当てメモリが急増しますが、割り当てメモリが安定するまで警告はスローされません。ただし、VM トラッカーのメモリは、スローされたときにまだ増加しています。これにより、コントロールがまだメモリにロードされており、VM トラッカーが警告の原因となっているメモリの増加のより良い指標であると思われます。通常、常駐サイズが 125 MB を超えると、警告が発生します。Resident のサイズを大幅に下げる 1 つの方法を見つけました。質問コントロールには、丸みを帯びたエッジとドロップ シャドウを与えるカスタム ビューがあります。カスタム ビューから drawRect コード (以下に示す) をコメント アウトすると、割り当てメモリは同じままですが、常駐サイズは約 30 MB 減少し、93 MB を超えることはありません。

- (void)drawRect:(CGRect)rect {
    // get the contect
    CGContextRef context = UIGraphicsGetCurrentContext();

    //for the shadow, save the state then draw the shadow
    CGContextSaveGState(context);
    CGContextSetShadow(context, CGSizeMake(4,-5), 10);

    //now draw the rounded rectangle
    CGContextSetStrokeColorWithColor(context, [[UIColor blackColor] CGColor]);  

    if(_HighlightColor==nil){
        _HighlightColor = [[UIColor whiteColor] retain];
    }
    CGContextSetFillColorWithColor(context, _HighlightColor.CGColor);

    //since I need room in my rect for the shadow, make the rounded rectangle a little smaller than frame
    CGRect rrect = CGRectMake(CGRectGetMinX(rect), CGRectGetMinY(rect), CGRectGetWidth(rect)-30, CGRectGetHeight(rect)-30);
    CGFloat radius = 5;
    // the rest is pretty much copied from Apples example
    CGFloat minx = CGRectGetMinX(rrect), midx = CGRectGetMidX(rrect), maxx = CGRectGetMaxX(rrect);
    CGFloat miny = CGRectGetMinY(rrect), midy = CGRectGetMidY(rrect), maxy = CGRectGetMaxY(rrect);

    // Start at 1
    CGContextMoveToPoint(context, minx, midy);
    // Add an arc through 2 to 3
    CGContextAddArcToPoint(context, minx, miny, midx, miny, radius);
    // Add an arc through 4 to 5
    CGContextAddArcToPoint(context, maxx, miny, maxx, midy, radius);
    // Add an arc through 6 to 7
    CGContextAddArcToPoint(context, maxx, maxy, midx, maxy, radius);
    // Add an arc through 8 to 9
    CGContextAddArcToPoint(context, minx, maxy, minx, midy, radius);
    // Close the path
    CGContextClosePath(context);
    // Fill & stroke the path
    CGContextDrawPath(context, kCGPathFillStroke);

    //for the shadow
    CGContextRestoreGState(context);
}

インストゥルメントとメモリの警告では、メモリが使い果たされているように見えますが、これらの数値は私には高いように見えます。スクロールビュー内のこれらの質問コントロールが 120 個あっても、iPad が処理するのに問題があるとは思いませんが、どれだけのメモリを消費する必要があるかについての基準フレームはありません。iPad で実行できるグラフィックを多用するゲームのいくつかを考慮すると、上記の単純な drawRect コードが質問コントロールで 30 MB 以上を消費するようには思えません。このメモリ使用量は高いように見えますか?それとも、これは多くのシンプルな UI 要素を持つアプリに期待されることですか? drawRect に多くのメモリを消費するものや、最適化する方法に関する提案はありますか? これで iPad のメモリが使い果たされるように思われる場合は、タブまたはページを作成し、タブまたはページに配置する質問の数を制限して、コントロールの一部のみが一度にメモリに読み込まれるようにします。ただし、iPad がそれらすべてをメモリ内で処理できる必要がある場合は、それらを分割したくありません。どんな入力でも大歓迎です。

4

2 に答える 2

4

割り当てたすべてのビューは、かなりのメモリを消費します。画面上(またはスクロールビューでは画面外)に多数のビューがある場合に大量のメモリを使用しないようにする方法は、再利用するビューのプールを用意し、常に画面に表示されているビューよりも少ないビューを使用することです。

悪いニュース:このキャッシングとスワッピングはセットアップがかなり複雑です。

良いニュース:UITableViewがあなたに代わってそれを行います!

UIViewの数が任意に多い場合、ほとんどの場合、それらをテーブルビューに配置し、Appleにハードワークを任せるのが最善の解決策です。

于 2012-02-07T07:30:50.330 に答える
2

ヒープ ショット分析(Instruments を使用) を使用して、メモリ デルタを割り当てバックトレースの詳細まで監視できます。これらの割り当ては、多くの場合、その期間中に何を破棄する必要があったかを示しています。

また、プログラムにリークがないことを確認してください。

于 2012-02-07T07:22:43.157 に答える