在iOS上有效地绘制有很多点的图表

时间:2016-01-19 21:35:46

标签: ios graph plot drawing core-graphics

我正在寻找一种方法在iOS上有效地绘制包含大量点数(最多10 000)的折线图。该图获取实时数据,需要每秒多次更新。我试图找出一种有效绘制图形的方法,这样它就不会最大化CPU并在绘制时阻塞主线程。

我目前在后台线程中为折线图创建UIBezierPath,添加所有点并将其绘制在CALayer中(启用了异步绘图)。它不是很快,最大化CPU和绘图是如此之慢,UI变得迟钝。我正在绘制实时数据,理论上我每次都可以重复使用相同的UIBezierPath并且只是追加新的点,但是旧的值会在一段时间后被丢弃,这意味着必须删除已删除值的点从bezier路径,这是不可能的。

我还没有在iOS上有效地绘制大型数据集,但我希望有办法使用GPU来提高性能。

3 个答案:

答案 0 :(得分:1)

几年前我遇到过这样的情况(早在iPhone 4天)。

我使用了CGMutablePathRef我使用CGPathMoveToPoint为第一个点添加了点数,CGPathAddLineToPoint用于后续点。

为了获得可接受的性能,我将数据点存储在C数组中(而不是NSArray)。此外,在绘制点时,如果其显示坐标与最后绘制的点相同,我只是跳过对CGPathAddLineToPoint的调用。 (当数据点多于像素时,通常会出现这种情况)。

我不记得确切的绘图时间,但它的速度令人惊讶。

答案 1 :(得分:0)

不是使用UIBezierPath绘制点,而是设置CGBitmapContext,然后用手绘制点",例如

color = (0xFF << 24) | (blue << 16) | (green << 8) | (red); // AABBGGRR
for (loop = 0; loop < count; loop++)
{
    index = indices[loop];
    self.pixels[index] = color;
}

其中self.pixels是您用于创建CGBitmapContext的缓冲区。然后,在drawRect:

CGContextRef c = UIGraphicsGetCurrentContext();

CGImageRef image = CGBitmapContextCreateImage(self.imageContext);
CGContextDrawImage(c, self.bounds, image);
CGImageRelease(image);

我认为您会发现这比使用CGPath或UIBezierPath要快得多(也就更小)。

答案 2 :(得分:0)

我终于找到了使用OpenGL绘制图形的实现:https://github.com/syedhali/EZAudio/blob/master/EZAudio/EZAudioPlotGL.m

实际上非常简单,性能提升也很大。

对于使用A7芯片(或更新版本)的设备,使用金属绘制图形可能会更快,这也应该非常简单。有一些指南如何执行此操作:https://www.raywenderlich.com/77488/ios-8-metal-tutorial-swift-getting-started