6

Antecedentes

lo tanto, con un IOS 6 UITextView puede tomar una attributedString, lo que podría ser útil para el resaltado de sintaxis.UITextView attributedText y resaltado de sintaxis

Estoy haciendo algunos patrones de expresiones regulares en -textView:shouldChangeTextInRange:replacementText: y muchas veces tengo que cambiar el color de una palabra ya escrita. No veo otras opciones aparte de restablecer el texto atribuido, lo que lleva tiempo.

- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text 
{ 
    //A context will allow us to not call -attributedText on the textView, which is slow. 
    //Keep context up to date 
    [self.context replaceCharactersInRange:range withAttributedString:[[NSAttributedString alloc] initWithString:text attributes:self.textView.typingAttributes]]; 

    // […] 

    self.textView.scrollEnabled = FALSE; 

    [self.context setAttributes:self.defaultStyle range:NSMakeRange(0, self.context.length)]; 
    [self refresh]; //Runs regex-patterns in the context 
  textView.attributedText = self.context; 

    self.textView.selectedRange = NSMakeRange(range.location + text.length, 0); 
    self.textView.scrollEnabled = TRUE; 

    return FALSE; 
} 

Esto va en okayish en el simulador, pero en un iPad 3 -setAttributedText cada toma unos pocos cientos de milisegundos.

He archivado un error en Apple, con la solicitud de poder mutar el texto atribuido. Se marcó como duplicado, por lo que no puedo ver lo que dicen sobre esto.

La pregunta

La pregunta más específica: ¿Cómo se puede cambiar el color de ciertos rangos en un UITextView, con un gran texto multicolor, con un buen rendimiento suficiente para hacerlo en todos los shouldReplaceText...?

La pregunta más amplia: ¿Cómo se resalta la sintaxis con una UITextView en iOS 6?

+0

También estoy tratando de resaltar el texto que se habla en mi aplicación web de altavoces. Pensé que sería capaz de hacerlo fácilmente con iOS6, pero no pude encontrar la API para cambiar el color de la cadena en cierto rango de forma dinámica. Establecer el texto completo atribuido cada vez lleva demasiado tiempo. –

+0

También archivé un informe de error a Apple. Necesitamos algo como este método. "textView_.attributedText addAttribute: value: font range:" –

+0

Sí, pero apuesto a que nunca veremos una versión mutable del attributeText, ya que textView necesita saber siempre que se cambie la cadena. Esperaría un setter más inteligente, o una versión atribuida de '-replaceRange: withText:' –

Respuesta

0

Los descriptores de acceso de attributeText tienen que desplazarse de ida y vuelta a/desde HTML, por lo que no es óptimo para una implementación de vista de texto resaltada por sintaxis. En iOS 6, es probable que desee utilizar CoreText directamente.

+0

No sé exactamente cómo funciona el HTML de textView, pero podría cambiar los atributos tan fácilmente como reemplazar texto en el DOM y actualizar el texto de textView, ¿o no? –

1

Me encontré con el mismo problema para mi aplicación Zap-Guitar (No-Strings-Attached) donde permití a los usuarios escribir/pegar/editar sus propias canciones y la aplicación resalta los acordes reconocidos.

Sí, es cierto apple utiliza un escritor html y un analizador para mostrar el texto atribuido. Una maravillosa explicación de detrás de la escena se puede encontrar aquí: http://www.cocoanetics.com/2012/12/uitextview-caught-with-trousers-down/

La única solución que encontré para este problema es no utilizar el texto atribuido que es una exageración para resaltar la sintaxis.

En su lugar volví al viejo viejo UITextView con texto sin formato y agregué botones a la vista de texto donde se necesitaba resaltar. Para calcular los marcos de los marcos utilicé esta respuesta: How to find position or get rect of any word in textview and place buttons over that?

Este uso reducido de la CPU en un 30% (más o menos).

Aquí es una categoría útil:

@implementation UITextView (WithButtons) 
- (CGRect)frameForTextRange:(NSRange)range { 
    UITextPosition *beginning = self.beginningOfDocument; 
    UITextPosition *start = [self positionFromPosition:beginning offset:range.location]; 
    UITextPosition *end = [self positionFromPosition:start offset:range.length]; 
    UITextRange *textRange = [self textRangeFromPosition:start toPosition:end]; 
    CGRect rect = [self firstRectForRange:textRange]; 
    return [self convertRect:rect fromView:self.textInputView]; 
} 

@end