2012-04-19 8 views
8

Ho scritto un'app per testare le prestazioni delle immagini su iOS. Ho provato 3 diverse visualizzazioni, tutte con lo stesso grande PNG. La prima è una vista che disegna usando CGContextDrawImage(). Il secondo imposta self.layer.content. Il terzo è un semplice UIImageView.UIImageView mostra MOLTO più veloce di CG o CALayer. Qualcuno sa perché?

L'immagine utilizzata viene creata utilizzando - [UIImage initWithContentsOfData:] e memorizzato nella cache nel viewController. Ogni test assegna ripetutamente una vista, la aggiunge alla gerarchia della vista, quindi la rimuove e la rilascia. I tempi sono presi dall'inizio di loadView a viewDidAppear e dati come fps (in pratica, visualizza i disegni al secondo).

Ecco i risultati da un iPad 1 in esecuzione 5.1 con un 912 x 634 immagine non in scala:

CGContext: 11 fps 
CALayer:  10 fps 
UIImageView: 430 fps (!) 

Am I allucinazioni? Sembra quasi impossibile che UIImageView sia in grado di disegnare così velocemente, ma posso effettivamente vedere lo sfarfallio delle immagini. Ho provato a scambiare tra due visualizzazioni simili per sconfiggere il possibile caching, ma il frame rate era ancora più alto.

Ho sempre pensato che UIImageView fosse solo un wrapper per - [CALayer setContent]. Tuttavia, la profilazione di UIImageView mostra quasi nessun tempo trascorso in alcun metodo di disegno che possa essere identificato.

Mi piacerebbe capire cosa sta succedendo. Qualsiasi aiuto sarebbe più apprezzato.

+1

Si prega di modificare la domanda per includere il codice che hai cronometrato in ciascuno dei casi, o un link ad esso. –

+0

Il codice fa parte di un'app più grande utilizzata per testare il nostro codice di gioco proprietario. Ci vorranno un paio d'ore per estrarre i pezzi rilevanti. Nel frattempo, sarei felice di fornirti tutti i dettagli specifici che ti mancano nella descrizione di cui sopra. –

+0

"I tempi sono presi dall'inizio di loadView per viewDidAppear" - sembra un po 'fasullo, dal momento che 'viewDidAppear' potrebbe essere chiamato prima che la vista venga visualizzata sullo schermo.Se non si sta forzando lo schermo ad aggiornare, non si è in grado di cronometrare nulla di utile; potresti creare e distruggere diverse UIImageViews ma solo una viene effettivamente disegnata. Mi chiedo se UIImageView stia impostando il contenuto del suo livello su richiesta in '-layoutSubviews' - ​​questo è certamente il modo in cui lo farei, per assicurarmi di aver toccato il livello solo una volta per aggiornamento dello schermo. –

risposta

1

Ecco la mia idea.

Quando si modifica una gerarchia di UIView, aggiungendo, rimuovendo o modificando una vista, non viene ancora eseguito alcun disegno effettivo. Invece la vista è marcata con 'setNeedsDisplay', e viene ridisegnata la prossima volta che runloop è libero di disegnare.

Infatti, se il codice di prova simile a questa (posso solo immaginare):

for (int i=0; i<10000; i++) { 
    UIImageView* imageView = [[UIImageView alloc] initWithFrame:frame]; 
    [mainView addSubview: imageView]; 
    [imageView setImage: image]; 
    [mainView removeSubview: imageView]; 
} 

rispetto al runloop è bloccato fino a quando questo ciclo for è fatto. La gerarchia della vista viene disegnata una sola volta, la prestazione misurata è quella di allocare e inizializzare gli oggetti.

D'altra parte, CGContextDrawImage() è libero di disegnare subito, penso.

+1

Sì, sicuramente non lo sto facendo. È una supposizione ragionevole, però. La mia sequenza di test ritorna al ciclo di esecuzione dopo ogni passaggio. Siamo nel bel mezzo di una grande uscita qui su Funzio, ma cercherò di ottenere una copia del progetto su Github domani presto. Grazie per l'aiuto. –

1

L'alto valore di FpS con UIImageView è dovuto al fatto che questo non viene effettivamente ridisegnato, ma segna il contenuto solo per ridisegnarlo a volte in futuro quando Uikit ha voglia di farlo.

Come nota: Ciò che è strano è che il metodo CGContext è più veloce di CALayermethod. Ho anche provato questi metodi in un mio progetto e lavorare con CALayer è il metodo più veloce (tranne ovviamente usando OpenGL ES).

Problemi correlati