objective-c - guide - objective c documentation
Rendimiento del texto principal (4)
Estoy viendo algunos problemas de rendimiento con Core Text cuando se ejecuta en el iPad original.
He creado una vista editable utilizando Core Text y el protocolo UITextInput
que se basa en el OUIEditableFrame
de OmniGroup.
Cuando hay una buena cantidad de texto en la vista, digamos 180 líneas, la escritura / entrada se retrasa considerablemente y un toque en una tecla generalmente toma de 1 a 2 segundos.
Usando instrumentos con el simulador, pude reducir el problema y descubrir lo que llevaba tanto tiempo. Resulta que es porque vuelvo a dibujar el marco con cada CTFramesetterCreateWithAttributedString
tecla, lo que lleva tanto tiempo es llamar a CTFramesetterCreateWithAttributedString
y CTFramesetterCreateFrame
.
Tengo que volver a dibujar con cada golpe de tecla para que el texto se actualice, esto significa llamar a CTFramesetterCreateWithAttributedString
y CTFramesetterCreateFrame
.
¿Alguien más se ha encontrado con este problema y, de ser así, cómo lo solucionaron?
EDITAR:
Investigé un poco más y resultó que si la cadena atribuida no tiene atributos, entonces todo se dibuja mucho más rápido y sin ningún retraso. Al cambiar la fuente, el color o el estilo de los párrafos, se ralentiza. ¿Alguna idea de si esto podría tener algo que ver con eso?
Desde mi pregunta original, investigué un poco más y descubrí que cuantos más atributos tiene la cadena dibujada, más tiempo lleva.
Con ese conocimiento, decidí simplemente eliminar / ocultar cualquier atributo (específicamente kCTForegroundColor
) que el usuario no pudo ver, esto aceleró el dibujo diez veces y lo convirtió en una experiencia mucho más útil.
He estado experimentando con el uso de CTLines
y un UITableView
en mis intentos de hacer resaltado de sintaxis en iOS. Lo mejor de tableView es que puede actualizar, eliminar e insertar una línea, y solo volver a dibujar esa línea.
CTFramesetterCreateWithAttributedString
es realmente lento. Así que cuanto menos lo uses mejor. Si el usuario escribe algo, no necesita volver a dividir todo el texto en líneas, puede actualizar la línea actual y, si está desbordada, puede insertar una nueva. Es un poco de trabajo hacer que funcione en todos los casos, pero el rendimiento podría ser increíble.
Esto es lo que he hecho: https://github.com/Anviking/Chromatism .
Probablemente no deberías usar CTFramesetter
para crear algo como UITextView
. En su lugar, es probable que deba mantener una serie de referencias CTLine
. Si necesita ayuda para separar palabras, entonces puede usar un CTTypeSetter
, pero solo necesita entregar las líneas en el caret actual e inferior (aún estará creando y destruyendo tipógrafos, así que tenga cuidado con lo que pide de ellos). ).
Una cosa buena de mantener una serie de CTLines
es que puede deshacerse de 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.
Un enfoque alternativo es continuar usando CTFramesetter, pero usar CTFrames más pequeños. Solo su NSAttributedString en subcadenas (por ejemplo, usando [NSString paragraphRangeForRange:] para obtener los rangos de párrafos y luego dividir su cadena atribuida utilizando el atributotribSubstringFromRange :). Luego crea un CTFrame por párrafo. Cuando algo cambia (por ejemplo, el usuario escribe algo), solo actualiza los CTFrame que cambiaron.
Esto significa que puede seguir aprovechándose de lo que CTFramesetter le ofrece sin la penalización de rendimiento de volver a configurar todo el texto cada vez.