我正在寻找一种方法在iOS上有效地绘制包含大量点数(最多10 000)的折线图。该图获取实时数据,需要每秒多次更新。我试图找出一种有效绘制图形的方法,这样它就不会最大化CPU并在绘制时阻塞主线程。
我目前在后台线程中为折线图创建UIBezierPath
,添加所有点并将其绘制在CALayer中(启用了异步绘图)。它不是很快,最大化CPU和绘图是如此之慢,UI变得迟钝。我正在绘制实时数据,理论上我每次都可以重复使用相同的UIBezierPath
并且只是追加新的点,但是旧的值会在一段时间后被丢弃,这意味着必须删除已删除值的点从bezier路径,这是不可能的。
我还没有在iOS上有效地绘制大型数据集,但我希望有办法使用GPU来提高性能。
答案 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