6

Sfondo

Così, con iOS 6 un'UITextView può assumere un attributedString, che potrebbe essere utile per evidenziare la sintassi.UITextView attributedText e l'evidenziazione della sintassi

Sto facendo alcuni schemi di espressioni regolari in -textView:shouldChangeTextInRange:replacementText: e spesso ho bisogno di cambiare il colore di una parola già digitata. Non vedo altre opzioni che resettare il testo attribuito, che richiede tempo.

- (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; 
} 

Questo viene eseguito okayish sul simulatore, ma su un iPad 3 ciascuno -setAttributedText prende un paio di centinaia di millisecondi.

Ho archiviato un bug su Apple, con la richiesta di poter modificare il testo attribuito. È stato contrassegnato come duplicato, quindi non riesco a vedere cosa stanno dicendo su questo.

La domanda

La domanda più specifica: Come posso cambiare il colore di alcune gamme in un UITextView, con un testo di grandi dimensioni multicolore, con buone prestazioni abbastanza da fare in ogni shouldReplaceText...?

La domanda più ampia: Come si esegue l'evidenziazione della sintassi con un UITextView in iOS 6?

+0

Sto anche cercando di evidenziare il testo che viene parlato in mio diffusore web app. Ho pensato che sarei stato in grado di farlo facilmente con iOS6, ma non sono riuscito a trovare l'api per modificare dinamicamente il colore delle corde in determinati intervalli. L'impostazione di testo attribuito completo ogni volta richiede troppo tempo. –

+0

Ho anche presentato una segnalazione di bug ad Apple. Abbiamo bisogno di qualcosa come questo metodo. "textView_.attributedText addAttribute: valore: intervallo di caratteri:" –

+0

Sì, ma scommetto che non vedremo mai una versione mutabile del testo attribuito, dal momento che textView deve sapere ogni volta che la stringa viene cambiata. Spero sia per un setter più intelligente, sia per una versione attribuita di '-replaceRange: withText:' –

risposta

0

Gli accessors del testo attribuiti devono eseguire il round-trip da/verso HTML, quindi è davvero non ottimale per un'implementazione della vista testuale evidenziata dalla sintassi. Su iOS 6, probabilmente vorrai usare direttamente il CoreText.

+0

Non so esattamente come funziona l'HTML di textView, ma potresti cambiare gli attributi con la stessa facilità di sostituire del testo nel DOM e aggiornare il testo di textView, no? –

1

Ho riscontrato lo stesso problema per la mia applicazione Zap-Guitar (No-Strings-Attached) in cui autorizzo gli utenti a digitare/incollare/modificare le proprie canzoni e l'app evidenzia accordi riconosciuti.

Sì, è vero che Apple utilizza uno scrittore e un parser html per visualizzare il testo attribuito. Una meravigliosa spiegazione di dietro la scena può essere trovata qui: http://www.cocoanetics.com/2012/12/uitextview-caught-with-trousers-down/

L'unica soluzione che ho trovato per questo problema non è quella di utilizzare il testo attribuito che è un eccessivo per l'evidenziazione della sintassi.

Invece ho ripristinato il buon vecchio UITextView con testo normale e pulsanti aggiunti alla vista testo dove era necessario evidenziare. Per calcolare i frame dei pulsanti ho usato questa risposta: How to find position or get rect of any word in textview and place buttons over that?

Questo utilizzo ridotto della CPU del 30% (dare o prendere).

Ecco una categoria a portata di mano:

@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