1

0.1 秒ごとに NSTimer を使用してグリッドからセルを描画しています。サイズは約 96x64 => 6144 セル/画像です。(たとえば)緑色の長方形の代わりに画像を描画している場合、4倍遅くなります!

- (void)drawRect:(CGRect)rect
{
    CGContextRef context = UIGraphicsGetCurrentContext();
    UIGraphicsPushContext(context);
    CGContextSetRGBFillColor(context, 0, 0, 0, 1);
    CGContextFillRect(context, CGRectMake(0, 0, self.bounds.size.width, self.bounds.size.height));
    int cellSize = self.bounds.size.width / WIDTH;
    double xOffset = 0;
    for (int i = 0; i < WIDTH;i++)
    {
        for (int j = 0; j < HEIGHT;j++)
        {                
                NSNumber *currentCell = [self.state.board objectAtIndex:(i*HEIGHT)+j];
                if (currentCell.intValue == 1)
                {
                   [image1 drawAtPoint:CGPointMake(xOffset + (cellSize * i),cellSize * j )];
                }
                else if (currentCell.intValue == 0){
                   [image2 drawAtPoint:CGPointMake(xOffset + (cellSize * i),cellSize * j )];
                }
        }
    }
    UIGraphicsPopContext();
}

各長方形にpngまたはjpgを描画したい場合、これをより速くする方法はありますか? 画像はすでに適切なサイズにスケーリングされています。

4

4 に答える 4

3
  • a) ビューの境界外にある画像/四角形を再描画しないでください。

  • b)dirtyRectの外側にある画像/四角形を再描画しないでください

  • c) 前回の更新以降に変更されていない画像/四角形を再描画しないでください。

  • d) レイヤーを使用して画像を事前にレンダリングするため、描画時にレンダリングする必要はありません。

于 2013-03-09T16:25:52.407 に答える
2

このシナリオはまさにInstrumentsの目的です。これを使って。ここで提案をしている人は誰でも、ボトルネックが何であるかを推測しています。

そうは言っても、私はボトルネックが何であるかを推測するつもりです。CPUを使用して6114枚の画像を描画しています(タイムプロファイラーを使用してこれを確認します。drawRectメソッドを見つけて、最も時間が費やされている場所を確認します。drawInRectの場合は、それが問題です)

その場合、どうすればその使用量を減らすことができますか?簡単な方法は、描画する必要のある画像のみを再描画することです。CALayersはこれを簡単にします。drawRectメソッドを削除し、各画像のビューのレイヤーにサブレイヤーを追加し、画像をレイヤーのコンテンツプロパティとして設定します。画像を変更する必要があるときにビューを無効にする代わりに、関連するレイヤーのコンテンツプロパティを新しい画像に切り替えるだけです。

CALayersのもう1つの優れた点は、GPUにレイヤーコンテンツをキャッシュすることです。つまり、再描画が行われると、必要なCPU時間が少なくなり、発生したときにアプリの残りの部分がブロックされることはありません。

その多くのレイヤーのオーバーヘッドが許容できない場合(ここでも、Instrumentsはあなたの友達です)、CAReplicatorLayerをチェックしてください。多くのCALayerを使用するよりも柔軟性は低くなりますが、最小限のオーバーヘッドで1つのイメージを何度も複製できます。

于 2013-03-09T23:50:20.413 に答える
1

パフォーマンスの観点からコードを改善しようとしました。ただし、ボトルネックに関する私のコメントも確認してください。

- (void)drawRect:(CGRect)rect {
    CGContextRef context = UIGraphicsGetCurrentContext();
    //UIGraphicsPushContext(context); //not needed UIView does it anyway

    //use [UIView backgroundColor] instead of this
    //CGContextSetRGBFillColor(context, 0, 0, 0, 1);
    //CGContextFillRect(context, CGRectMake(0, 0, self.bounds.size.width, self.bounds.size.height));

    int cellSize = self.bounds.size.width / WIDTH;
    double xOffset = 0;

    CGRect cellFrame = CGRectMake(0, 0, cellSize, cellSize);
    NSUinteger cellIndex = 0;

    for (int i = 0; i < WIDTH; i++) {
        cellFrame.origin.x = xOffset;

        for (int j = 0; j < HEIGHT; j++, cellIndex++) {                
            cellFrame.origin.y = 0;

            if (CGRectIntersectsRect(rect, cellFrame) {
                NSNumber *currentCell = [self.state.board objectAtIndex:cellIndex];

                if (currentCell.intValue == 1) {
                    [image1 drawInRect:cellFrame];
                }
                else if (currentCell.intValue == 0) {
                    [image2 drawInRect:cellFrame];
                }
            }

            cellFrame.origin.y += cellSize;
        }

        cellFrame.origin.x += cellSize;
    }

    //UIGraphicsPopContext(context); //not needed UIView does it anyway
}
于 2013-03-09T17:12:20.343 に答える
0

CGRectIntersects画像の四角形がdirtyRectの内側にあるかどうかを確認して、描画する必要があるかどうかを確認するために使用します。

于 2013-03-09T16:46:01.563 に答える