325 votos

Rápido y sencillo Visor de PDF para iPhone / iPad / iOs - consejos y sugerencias?

Ha habido muchas Preguntas recientemente sobre el dibujo PDF.

Sí, usted podrá convertir archivos PDF muy fácilmente con un UIWebView pero esto cant dar el rendimiento y la funcionalidad que se puede esperar de un buen visor de PDF.

Usted puede dibujar una página de un PDF a un CALayer o a un UIImage. Apple incluso tiene código de ejemplo para mostrar cómo dibujar un PDF de gran tamaño en un Zoom UIScrollview

Pero los mismos problemas de mantener el recorte.

UIImage Método:

  1. PDF en un UIImage no ópticamente la escala así como una Capa de enfoque.
  2. La CPU y la memoria de golpe en la generación de la UIImages de un PDFcontext límites y evita que se utilice para crear una en tiempo real de procesamiento de nuevo zoom-niveles.

CATiledLayer Método:

  1. Hay una Sobrecarga significativa (tiempo) dibujo de un PDF completo página a un CALayer: fichas individuales puede ser visto de representación (incluso con un tamañobaldosa modificar)
  2. CALayers cant ser preparados antes de tiempo (prestados fuera de la pantalla).

Generalmente los visores de PDF son bastante pesados en la memoria. Incluso supervisar el uso de memoria de apple con zoom PDF de ejemplo.

En mi proyecto actual, estoy desarrollando un visor de PDF y soy de representación de una UIImage de una página en un hilo separado (cuestiones aquí también!) y presentarlo mientras que la escala es x1. CATiledLayer de representación se activa una vez que la escala es >1. iBooks toma una similar doble toma el enfoque de como si se desplaza por las páginas puede ver una menor resolución de la versión de la página, con un poco menos de un segundo antes de un crujiente de versión aparece.

Im representación de 2 páginas cada lado de la página en el foco, de modo que la imagen de PDF está listo para la máscara de la capa antes de que comience drawing.Pages son destruidas cuando son +2 páginas de distancia desde el enfoque de la página.

¿Alguien tiene algún conocimiento, no importa cuán pequeño o evidente para mejorar el rendimiento y el manejo de la memoria de Dibujo PDF? o cualquier otros temas discutidos aquí?

EDIT: Algunos Consejos (Crédito - Lucas Mcneice,VdesmedT,Matt Gallagher,Johann):

  • Guardar cualquier medio de comunicación en el disco cuando usted puede.

  • Utilizar mayor tileSizes si el procesamiento en TiledLayers

  • init utiliza con frecuencia matrices con objetos de marcador de posición, alternitively otro enfoque de diseño es este uno de los

  • Tenga en cuenta que las imágenes se procesan más rápido que un CGPDFPageRef

  • Uso NSOperations o GCD y Bloques para preparar páginas por delante de tiempo.

  • llame CGContextSetInterpolationQuality(ctx, kCGInterpolationHigh); CGContextSetRenderingIntent(ctx, kCGRenderingIntentDefault); antes CGContextDrawPDFPage para reducir el uso de memoria mientras dibujo

  • init ing su NSOperations con una opinión, es una mala idea (de la memoria), la envoltura de la opinión en un singleton.

  • Cancelar innecesario NSOperations Cuando es posible, especialmente si se va a utilizar la memoria, el cuidado de dejar a los contextos abiertos, aunque!

  • Reciclar los objetos de la página haciendo puntero swaps o destruir sin usar vistas

  • Cierre todos los Contextos tan pronto como usted no los necesita

  • en la recepción de la memoria advertencias suelte y vuelva a cargar la Opinión y cualquier página de Cachés

Otras Características de PDF:

Documentación

Ejemplo de proyectos

94voto

VdesmedT Puntos 6831

He construir este tipo de aplicación que utiliza aproximadamente el mismo enfoque, con excepción de :

  • Yo caché de la imagen generada en el disco y siempre generan dos a tres imágenes en avanzar en un subproceso independiente.
  • Yo no superposición con un UIImage pero en lugar de dibujar la imagen en la capa cuando se usa el zoom 1. Los azulejos serán liberados automáticamente cuando la memoria se emiten advertencias.

Cada vez que el usuario inicie la operación del zoom, puedo adquirir el CGPDFPage y hacen uso de la correspondiente MARCA. El código en - (void)drawLayer: (CALayer*)layer inContext: (CGContextRef) context es como :

CGAffineTransform currentCTM = CGContextGetCTM(context);    
if (currentCTM.a == 1.0 && baseImage) {
    //Calculate ideal scale
    CGFloat scaleForWidth = baseImage.size.width/self.bounds.size.width;
    CGFloat scaleForHeight = baseImage.size.height/self.bounds.size.height; 
    CGFloat imageScaleFactor = MAX(scaleForWidth, scaleForHeight);

    CGSize imageSize = CGSizeMake(baseImage.size.width/imageScaleFactor, baseImage.size.height/imageScaleFactor);
    CGRect imageRect = CGRectMake((self.bounds.size.width-imageSize.width)/2, (self.bounds.size.height-imageSize.height)/2, imageSize.width, imageSize.height);
    CGContextDrawImage(context, imageRect, [baseImage CGImage]);
} else {
    @synchronized(issue) { 
        CGPDFPageRef pdfPage = CGPDFDocumentGetPage(issue.pdfDoc, pageIndex+1);
        pdfToPageTransform = CGPDFPageGetDrawingTransform(pdfPage, kCGPDFMediaBox, layer.bounds, 0, true);
        CGContextConcatCTM(context, pdfToPageTransform);    
        CGContextDrawPDFPage(context, pdfPage);
    }
}

problema es el objeto que contiene la CGPDFDocumentRef. Puedo sincronizar la parte donde puedo acceder a la pdfDoc de la propiedad debido a que me suelte y vuelva a crearla al recibir memoryWarnings. Parece que el CGPDFDocumentRef objeto de hacer algunas interna de almacenamiento en caché que no he podido encontrar la manera de deshacerse de.

64voto

De una forma sencilla y eficaz visor de PDF, cuando se requiere sólo una funcionalidad limitada, ahora puede (iOS 4.0+) usar la QuickLook marco:

QLPreviewController *previewController = [[QLPreviewController alloc] init];
previewController.dataSource = self;
previewController.delegate = self;
previewController.currentPreviewItemIndex = indexPath.row;
[self presentModalViewController:previewController animated:YES];
[previewController release];

Es necesario vincular en contra de QuickLook.framework y #import <QuickLook/QuickLook.h>

-1voto

Kuldeep singh Puntos 10
 CGAffineTransform currentCTM = CGContextGetCTM(context);     if
 (currentCTM.a == 1.0 && baseImage)  {
     //Calculate ideal scale
     CGFloat scaleForWidth = baseImage.size.width/self.bounds.size.width;
     CGFloat scaleForHeight = baseImage.size.height/self.bounds.size.height; 
     CGFloat imageScaleFactor = MAX(scaleForWidth, scaleForHeight);
     CGSize imageSize = CGSizeMake(baseImage.size.width/imageScaleFactor,
 baseImage.size.height/imageScaleFactor);
     CGRect imageRect = CGRectMake((self.bounds.size.width-imageSize.width)/2,
 (self.bounds.size.height-imageSize.height)/2, imageSize.width,
 imageSize.height);
     CGContextDrawImage(context, imageRect, [baseImage CGImage]); }  else  {
     @synchronized(issue)  { 
         CGPDFPageRef pdfPage = CGPDFDocumentGetPage(issue.pdfDoc, pageIndex+1);
         pdfToPageTransform = CGPDFPageGetDrawingTransform(pdfPage, kCGPDFMediaBox, layer.bounds, 0, true);
         CGContextConcatCTM(context, pdfToPageTransform);    
         CGContextDrawPDFPage(context, pdfPage);
     } }

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by: