2011-05-19 5 views
15

Estoy viendo algunos problemas de rendimiento con Core Text cuando se ejecuta en el iPad original.Core Text Performance

He creado una vista editable utilizando Core Text y el protocolo UITextInput que se basa en OmniGroup's OUIEditableFrame.

Cuando hay una buena cantidad de texto en la vista, digamos 180 líneas, la escritura/entrada se retrasa mucho y un toque en una tecla generalmente demora 1-2 segundos.

Usando instrumentos con el simulador pude reducir el problema y descubrir lo que estaba tomando tanto tiempo. Resulta que es porque vuelvo a dibujar el cuadro con cada golpe de tecla, lo que ocupa mucho tiempo es llamar al CTFramesetterCreateWithAttributedString y CTFramesetterCreateFrame.

Tengo que volver a dibujar con cada golpe de tecla para que el texto se actualice, esto significa llamar al CTFramesetterCreateWithAttributedString y CTFramesetterCreateFrame.

¿Alguien más ha encontrado este problema y, de ser así, cómo lo han solucionado?


EDIT:

hecho un poco de investigar más a fondo y resulta que si la cadena no tiene atributos atribuido a continuación, todo lo dibuja de modo mucho más rápido y sin ningún tipo de retraso. Cambiar el estilo de la fuente, el color o los párrafos todo lo ralentiza. ¿Alguna idea de si esto podría tener algo que ver con eso?

Respuesta

5

Desde mi pregunta original, investigué un poco más y descubrí que cuantos más atributos tenga la cuerda dibujada, más tiempo llevará.

Con ese conocimiento, decidí simplemente eliminar/ocultar los atributos (específicamente kCTForegroundColor) que el usuario no podía ver, esto aceleró diez veces el dibujo y lo hizo una experiencia mucho más útil.

+0

¿Puedes elaborar más sobre cómo eliminar/ocultar cualquier atributo? – adit

+0

Obtenga el rango de la parte visible de la vista de texto, recorra todos los atributos de la cadena atribuida y luego elimine los que no estén en ese rango. – Joshua

+0

Puedo confirmar esto: estaba usando un solo atributo personalizado con diferentes valores dependiendo de la ubicación en la cadena. Quitarlo produjo un aumento de velocidad de 5X en CTFramesetterCreateFrame(). Los otros 2 atributos que utilicé que tenían el mismo valor para toda la cadena no tuvieron impacto en el rendimiento. – Pol

8

Probablemente no deba usar CTFramesetter para crear algo como UITextView. En cambio, es probable que deba mantener una matriz de referencias CTLine. Si necesitas ayuda para romper palabras, entonces puedes usar un CTTypeSetter, pero solo tienes que pasarle las líneas al símbolo de carátula actual y debajo (aún crearás y destruirás un poco a los tipográficos, así que ten cuidado de lo que les pides)

Lo bueno de mantener una matriz de CTLines es que puede tirar los que no necesita si tiene poca memoria y reconstruirlos más tarde. Simplemente haga un seguimiento del rango de caracteres para cada línea.

+1

Eso definitivamente suena como una forma más eficiente de hacerlo. ¿Hay algún ejemplo de esto en Internet porque todos los que puedo encontrar utilizan 'CTFrameSetter'. – Joshua

+1

No he visto muchos buenos ejemplos de Core Text por ahí. He avanzado y redactado parte del trabajo que he realizado aquí: http://robnapier.net/blog/laying-out-text-with-coretext-547. No es exactamente lo mismo, pero puede darte algunos consejos en la dirección correcta. –

1

Un enfoque alternativo es continuar utilizando CTFramesetter, pero use CTFrames más pequeños. Solo su NSAttributedString en subcadenas (por ejemplo, usando [NSString paragraphRangeForRange:] para obtener rangos de párrafo y luego rompa su cadena atribuida usando attributedSubstringFromRange :). Luego crea un CTFrame por párrafo. Cuando algo cambia (por ejemplo, el usuario escribe algo), solo actualiza los CTFrame (s) que cambiaron.

Esto significa que debe seguir aprovechando lo que CTFramesetter le brinda sin la penalización de rendimiento de volver a configurar todo el texto todo el tiempo.

+0

Eso suena bien, pero un problema adicional es que si el texto se ejecuta en una nueva línea en un párrafo, tendría que cambiar cada párrafo después de eso para que no se superpongan. – Joshua

+0

Tiene razón, por lo que hay un golpe de rendimiento cada vez que se agrega una nueva línea, pero solo entonces. Y, afortunadamente, puede salir con un rendimiento ligeramente peor en este caso, ya que los ojos del usuario tienen que volver al principio de la línea. –

0

He estado experimentando con el uso de CTLines y un UITableView en mis intentos de resaltar la sintaxis en iOS. Lo mejor de tableView es que puedes actualizar, eliminar e insertar una línea, y solo volver a dibujar esa línea.

CTFramesetterCreateWithAttributedString es muy lento. Por lo tanto, cuanto menos lo uses, mejor. Si el usuario escribe algo, no necesita dividir todo el texto en líneas nuevamente, puede actualizar la línea actual y, si se desborda, puede insertar una nueva. Trabajar un poco para que funcione en todos los casos, pero el rendimiento podría ser increíble.

Esto que he hecho: https://github.com/Anviking/Chromatism.

+0

Ese proyecto se ve muy bien, y lo he examinado bien. ¡Muchas gracias! – Joshua