0.5 秒ごとに表示される値から折れ線グラフを描画する必要があります。このグラフのカスタム CALayer を思いつきました。これは、以前のすべての行を保存し、2 秒ごとに以前のすべての行を再描画して新しい行を 1 つ追加します。レイヤーに追加の線を 1 つ描画するだけでよく、以前の何千もの線を再描画する必要がないため、このソリューションは最適ではありません。
この場合の最善の解決策は何だと思いますか?
0.5 秒ごとに表示される値から折れ線グラフを描画する必要があります。このグラフのカスタム CALayer を思いつきました。これは、以前のすべての行を保存し、2 秒ごとに以前のすべての行を再描画して新しい行を 1 つ追加します。レイヤーに追加の線を 1 つ描画するだけでよく、以前の何千もの線を再描画する必要がないため、このソリューションは最適ではありません。
この場合の最善の解決策は何だと思いますか?
独自のNSBitmapContext
、またはUIImage
バッキング ストアとして使用します。新しいデータがこのコンテキストに描画されるたびに、レイヤーのcontents
プロパティをコンテキストの画像に設定します。
私は同じ実装を見ています。グラフは500ミリ秒ごとに更新されます。同様に、反復ごとにグラフ全体を描画することに不快感を覚えました。NikolaiRuheが提案したものと「類似した」ソリューションを次のように実装しました。
最初のいくつかの宣言:
#define TIME_INCREMENT 10
@property (nonatomic) UIImage *lastSnapshotOfPlot;
次に、CALayerデリゲートのdrawLayer:inContextメソッド
- (void) drawLayer:( CALayer*)layer inContext:(CGContextRef)ctx
{
// Restore the image of the layer from the last time through, if it exists
if( self.lastSnapshotOfPlot )
{
// For some reason the image is being redrawn upside down!
// This block of code adjusts the context to correct it.
CGContextSaveGState(ctx);
CGContextTranslateCTM(ctx, 0, layer.bounds.size.height);
CGContextScaleCTM(ctx, 1.0, -1.0);
// Now we can redraw the image right side up but shifted over a little bit
// to allow space for the new data
CGRect r = CGRectMake( -TIME_INCREMENT, 0, layer.bounds.size.width, layer.bounds.size.height );
CGContextDrawImage(ctx, r, self.lastSnapshotOfPlot.CGImage );
// And finally put the context back the way it was
CGContextRestoreGState(ctx);
}
CGContextStrokePath(ctx);
CGContextSetLineWidth(ctx, 2.0);
CGContextSetStrokeColorWithColor(ctx, [UIColor blueColor].CGColor );
CGContextBeginPath( ctx );
// This next section is where I draw the line segment on the extreme right end
// which matches up with the stored graph on the image. This part of the code
// is application specific and I have only left it here for
// conceptual reference. Basically I draw a tiny line segment
// from the last value to the new value at the extreme right end of the graph.
CGFloat ppy = layer.bounds.size.height - _lastValue / _displayRange * layer.bounds.size.height;
CGFloat cpy = layer.bounds.size.height - self.sensorData.currentvalue / _displayRange * layer.bounds.size.height;
CGContextMoveToPoint(ctx,layer.bounds.size.width - TIME_INCREMENT, ppy ); // Move to the previous point
CGContextAddLineToPoint(ctx, layer.bounds.size.width, cpy ); // Draw to the latest point
CGContextStrokePath(ctx);
// Finally save the entire current layer to an image. This will include our latest
// drawn line segment
UIGraphicsBeginImageContext(layer.bounds.size);
[layer renderInContext: UIGraphicsGetCurrentContext()];
self.lastSnapshotOfPlot = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
}
これが最も効率的な方法ですか?私はObjectiveCでプログラミングをしていないので、すべての提案/改善を歓迎します。