Cuadro de dibujo con muchos puntos de manera eficiente en iOS

Estoy buscando una manera de dibujar un gráfico lineal con muchos puntos (hasta 10 000) de manera eficiente en iOS. El gráfico obtiene datos en time real y debe actualizarse varias veces por segundo. Estoy tratando de encontrar una manera de dibujar el gráfico de manera eficiente para que no se maximice la CPU y se bloquee el hilo principal mientras se dibuja.

Actualmente estoy creando un UIBezierPath para el gráfico de líneas, en un hilo de background, agregando todos los puntos y dibujándolo en un CALayer (que tiene habilitado el dibujo asíncrono). No es muy rápido, maximiza la CPU y el dibujo es tan lento que la interfaz de usuario se vuelve floja. Estoy planeando datos en time real y, en teoría, podría reutilizar el mismo UIBezierPath cada vez y simplemente añadir los nuevos puntos, sin embargo, los valores más antiguos se descartan después de un time, lo que significa que los puntos de los valores eliminados tendrían que eliminarse de la ruta Bézier , que no es posible

No he encontrado nada en la planificación eficiente de grandes sets de datos en iOS, pero espero que haya forms de usar la GPU para boost el performance.

Tuve una situación como esta hace unos años (en iPhone 4 días).

Utilicé un CGMutablePathRef al que agregué puntos usando CGPathMoveToPoint para el primer punto, y CGPathAddLineToPoint para los puntos posteriores.

Para get un performance aceptable, almacené los puntos de datos en una matriz C (no una NSArray ). Además, al trazar un punto, si sus coorderadas de visualización eran las mismas que el último punto trazado, simplemente CGPathAddLineToPoint la llamada a CGPathAddLineToPoint . (Esto suele ser el caso cuando tienes más puntos de datos que píxeles).

No recuerdo el time de dibujo exacto, pero fue sorprendentemente rápido.

En lugar de graficar puntos usando UIBezierPath , puede configurar un CGBitmapContext y luego graficar los puntos "a mano", ej.

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

donde self.pixels es el búfer que usaste para crear el CGBitmapContext. Luego, en drawRect:

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

Creo que encontrarás que esto es significativamente más rápido (y más pequeño) que usar CGPath o UIBezierPath.

Finalmente encontré una implementación para dibujar un gráfico con OpenGL: https://github.com/syedhali/EZAudio/blob/master/EZAudio/EZAudioPlotGL.m

En realidad, es bastante fácil y las mejoras en el performance son enormes.

Para los dispositivos con el chip A7 (o más nuevo), probablemente sea aún más rápido dibujar el gráfico con metal, lo que también debería ser bastante fácil. Hay algunas guías sobre cómo hacerlo: https://www.raywenderlich.com/77488/ios-8-metal-tutorial-swift-getting-started