2010-08-09 5 views
8

ecco il codice:Perché questo codice CATiledLayer/PDF è lento?

https://www.dropbox.com/s/o42wy36x4qhrbpt/PDFScroller.zip

Ho preso il WWDC 2010 di codice PhotoScroller esempio che implementa annidato UIScrollViews per lo zoom, all'interno di un UIScrollView per il paging, e scambiati che cosa ho pensato che sarebbe minima quantità di codice necessario per visualizzare un PDF multipagina invece di immagini.

Funziona. Ma è lento sul mio iPhone4, circa tre secondi per dipingere la prima pagina, e ancora più lento sul mio iPod Touch. Posso vederlo dipingere le singole tessere. Questo stesso PDF si apre già più rapidamente, senza disegno di tile visibile, in un'implementazione CATiledLayer alternativa che utilizza semplicemente un singolo CATiledLayer/UIScrollView e tocca gli eventi per cambiare pagina. Mi piacerebbe usare questa tecnica PhotoScroller, è molto bella.

L'ho guardato con CPU Sampler in Instruments, e non sembra essere il codice di rendering PDF, sembra che il tempo sia occupato dal threading e dalla messaggistica. Sarei grato se qualcuno potesse aiutare a sottolineare cosa sta facendo questo esempio per sostenere il sovraccarico.

Grazie,

Jim


Update 1: avevo usato in origine la tecnica TilingView classe dal codice di esempio di definire

+ (Class) layerClass { 
    return [CATiledLayer class]; 
} 

E poi il disegno in - (void)drawRect:(CGRect)rect ma passato a la sottoclasse esplicita CATiledLayer come primo tentativo di vedere se avrebbe fatto la differenza, ma non lo fece, e quindi ho lasciato il codice così com'è per la pubblicazione qui. C'è anche una perdita [tiledLayer release]; mancante in TilingView.

+0

Sei riuscito a trovare una soluzione per questo? Stavo lavorando allo stesso. –

+0

Sì, l'aumento delle dimensioni della piastrella migliora in modo significativo le prestazioni. – jbm

+0

Ottenuto, ha appena aggiunto una nuova riga nel codice: tiledLayer.tileSize = CGSizeMake (512, 512); Ha funzionato davvero bene! Grazie. –

risposta

2

poiché il codice contiene un paio di errori e non riesco a compilare il codice, ma ho dato un'occhiata al file PDF che è stato incluso nell'archivio e conosco il motivo per cui TilingView è lento.

Normalmente quando si disegna una pagina pdf in un CGContext utilizzando il metodo CGContextDrawPDFPage:, tutto il testo e la grafica vettoriale sono stati renderizzati e altre cose come la normale grafica nel PDF vengono semplicemente disegnate e memorizzate nella cache. Quindi non importa quanto sia grande il file PDF, ma è importante se hai grahics vettoriali nel tuo PDF. Sembra che tu abbia una grafica vettoriale nel tuo PDF e anche alcune equazioni matematiche, questo è il motivo per cui è lento. Ti suggerisco di provare con un altro file PDF che non contiene grafica vettoriale e vedere se è più veloce.

Acclamazioni

Zheng

non
+0

Zheng, grazie per la tua risposta. Sul mio computer il codice viene creato e eseguito con l'ultimo SDK di iOS 4.0.2. E per quanto riguarda il contenuto del file PDF, sfortunatamente, non riesco a scegliere quale PDF i miei utenti decidono di provare a visualizzare, devo semplicemente fare del mio meglio con qualsiasi documento PDF valido. – jbm

1

congettura da prendere con qualsiasi tipo di autorità: PDF è un formato basato vettore per la maggior parte dei documenti (esclusi quelli che si limitano a servire come contenitore per le immagini TIFF incorporati) . Pertanto, quando si affianca il PDF come PhotoScroller, in sostanza si chiede al telefono di ridimensionare e rasterizzare l'intero PDF (almeno la pagina indicata) per ogni singola piastrella. Quindi, piuttosto che dipingerlo una volta come potresti per un singolo CATiledLayer, lo fai più volte per ogni risoluzione. Poiché il PDF è un formato scalabile in sé, dovresti essere in grado di eseguire il rendering dell'intera vista una sola volta per ogni pagina/scala.

Aggiornamento: Avendo appena eseguito questa operazione personalmente, l'esempio di PhotoScroller ha alcuni problemi logici che lo rendono molto lento. Fondamentalmente esegue il rendering di ogni piastrella su 1/ZoomScala, poi ridimensiona verso il basso per ingrandireScala. Quindi, se lo zoom è a .5, il rendering viene convertito in 2x, quindi ridimensionato a 0.5x. Molto lento e inefficiente.

+1

D'accordo, e CATiledLayer dovrebbe occuparsene per te, giusto? Sarebbe bello avere un output diagnostico o anche un'API delegata di quella classe per farci sapere come si comporta la memorizzazione nella cache, in base alle proprietà impostate: dimensione della piastrella, dettaglio, distorsione dei dettagli. Suppongo che abbiano bisogno di spazio per modificare l'algoritmo. – jbm