¿Cómo es que los iBooks representan la vista de índice tan rápido al ver un PDF? O bien: ¿cómo dibujar UIImages en UIScrollView directamente sin UIImageView?

Tengo un PDF de testing de 140 páginas (la especificación completa de Adobe PDF, http://wwwimages.adobe.com/www.adobe.com/content/dam/Adobe/en/devnet/pdf/pdfs/adobe_supplement_iso32000.pdf ) y abierto en iBooks. Luego cambia a la vista de índice (miniatura). Si me desploop hasta el final lo suficientemente rápido puedo ver que puedo desplazarme más rápido que iBooks hace las páginas, pero se pone al día rápidamente en iPad 2. Aprendo dos cosas de esto:

  • First iBooks muestra 140 cuadrados vacíos en el tamaño correcto y luego rellena la vista previa.
  • iBooks realmente muestra todas las vistas previas y las guarda en la memory (si me desploop, no puedo ver ninguna representación)
  • También probé con otra Adobe Spec que tiene más de 700 páginas: ¡exactamente el mismo comportamiento! ¡Fascinante!

La pregunta es ¿cómo lo están haciendo? Escribí un código que obtiene cada página del PDF como una image, la agrega a UIImageView y la agrega a la vista de desplazamiento.

Utilizo la misma técnica y layout que hace iBooks. Se vuelve tan rápido como iBooks, pero el consumo de memory es una locura y, especialmente, cuando se desplaza la aplicación se queda completamente atrapada después de un time. ¿Alguien puede apuntarme en la dirección correcta? Ya eliminé el renderizado PDF para las testings y es realmente rápido, por lo que puedo fijarlo a la generación de miniaturas.

EDITAR: Si desde el código siguiente se elimina la generación de PDF y se devuelve un UIImageView vacío, el performance aún es extremadamente débil. Entonces, mi suposition es que el UIImageView está causando el problema. ¿Cómo puedo dibujar los pulgares de PDF en mi UIScrollView sin el requisito de 140 UIImageViews ?

Para los que están firmes en Monotouch, aquí está el código que estoy usando para mostrar los pulgares, tal vez muestra una debilidad obvia:

 /// <summary> /// Gets the low res page preview of a PDF page. Does a quick image render of the page. /// </summary> /// <param name="iPage">the number of the page to render</param> /// <param name="oTergetRect">the target rect to fit the PDF page into</param> /// <returns> /// The low res page image view. /// </returns> public static UIImageView GetLowResPagePreview (CGPDFPage oPdfPage, RectangleF oTargetRect) { RectangleF oOriginalPdfPageRect = oPdfPage.GetBoxRect (CGPDFBox.Media); RectangleF oPdfPageRect = PdfViewerHelpers.RotateRectangle( oPdfPage.GetBoxRect (CGPDFBox.Media), oPdfPage.RotationAngle); // If preview is requested for the PDF index view, render a smaller version. if (!oTargetRect.IsEmpty) { // Resize the PDF page so that it fits the target rectangle. oPdfPageRect = new RectangleF (new PointF (0, 0), GetFittingBox (oTargetRect.Size, oPdfPageRect.Size)); } // Create a low res image representation of the PDF page to display before the TiledPDFView // renders its content. int iWidth = Convert.ToInt32 ( oPdfPageRect.Size.Width ); int iHeight = Convert.ToInt32 ( oPdfPageRect.Size.Height ); CGColorSpace oColorSpace = CGColorSpace.CreateDeviceRGB(); CGBitmapContext oContext = new CGBitmapContext(null, iWidth, iHeight, 8, iWidth * 4, oColorSpace, CGImageAlphaInfo.PremultipliedLast); // First fill the background with white. oContext.SetFillColor (1.0f, 1.0f, 1.0f, 1.0f); oContext.FillRect (oOriginalPdfPageRect); // Scale the context so that the PDF page is rendenetworking // at the correct size for the zoom level. oContext.ConcatCTM ( oPdfPage.GetDrawingTransform ( CGPDFBox.Media, oPdfPageRect, 0, true ) ); oContext.DrawPDFPage (oPdfPage); CGImage oImage = oContext.ToImage(); UIImage oBackgroundImage = UIImage.FromImage( oImage ); oContext.Dispose(); oImage.Dispose (); oColorSpace.Dispose (); UIImageView oBackgroundImageView = new UIImageView (oBackgroundImage); oBackgroundImageView.Frame = new RectangleF (new PointF (0, 0), oPdfPageRect.Size); oBackgroundImageView.ContentMode = UIViewContentMode.ScaleToFill; oBackgroundImageView.UserInteractionEnabled = false; oBackgroundImageView.AutoresizingMask = UIViewAutoresizing.None; return oBackgroundImageView; } internal static RectangleF RotateRectangle ( RectangleF oRect, int iRotationAngle ) { if ( iRotationAngle == 90 || iRotationAngle == 270 ) { return new RectangleF (oRect.X, oRect.Y, oRect.Height, oRect.Width); } return oRect; } 

¡No deberías usar 140 UIImageViews! use solo lo suficiente para llenar el área y luego recicle los que ya no se muestran.

¿Cómo implementó Apple UITableView? ¿Crees que guardan todas las celdas de la table en la memory?

Mire el código de muestra de PhotoScroller y el video WWDC 2010 correspondiente. Creo que se denomina "Desigining apps with scrollViews"

El video WWDC 2011 de nombre similar es la continuación del mismo truco de la reutilización de la vista.

Espero que esto ayude.

¿Has comprobado el tamaño de cada UIImageView ? Tal vez cada una de tus miniaturas sea del tamaño de una página completa.

¿Quizás iBooks no pone cada miniatura en un UIImageView ? Tal vez la aplicación está utilizando algo de CoreAnimation o incluso OpenGL ES?