Fast and Lean PDF Viewer for iPhone / iPad / iOS – tips and hints?

There has been many Questions recently about drawing PDF’s.

Yes, you can render PDF’s very easily with a UIWebView but this cant give the performance and functionality that you would expect from a good PDF viewer.

You can draw a PDF page to a CALayer or to a UIImage. Apple even have sample code to show how draw a large PDF in a Zoomable UIScrollview

But the same issues keep cropping up.

UIImage Method:

  1. PDF’s in a UIImage don’t optically
    scale as well as a Layer approach.
  2. The CPU and memory hit on generating
    the UIImages from a PDFcontext
    limits/prevents using it to create a
    real-time render of new zoom-levels.

CATiledLayer Method:

  1. Theres a significant Overhead (time)
    drawing a full PDF page to a CALayer: individual tiles can be seen rendering (even with a tileSize tweak)
  2. CALayers cant be prepared ahead of
    time (rendered off-screen).

Generally PDF viewers are pretty heavy on memory too. Even monitor the memory usage of apple’s zoomable PDF example.

In my current project, I’m developing a PDF viewer and am rendering a UIImage of a page in a separate thread (issues here too!) and presenting it while the scale is x1. CATiledLayer rendering kicks in once the scale is >1. iBooks takes a similar double take approach as if you scroll the pages you can see a lower res version of the page for just less than a second before a crisp version appears.

Im rendering 2 pages each side of the page in focus so that the PDF image is ready to mask the layer before it starts drawing.Pages are destroyed again when they are +2 pages away from the focused page.

Does anyone have any insights, no matter how small or obvious to improve the performance/ memory handling of Drawing PDF’s? or any other issues discussed here?

EDIT: Some Tips (Credit- Luke Mcneice,VdesmedT,Matt Gallagher,Johann):

  • Save any media to disk when you can.

  • Use larger tileSizes if rendering on TiledLayers

  • init frequently used arrays with placeholder objects, alternitively another design approach is this one

  • Note that images will render faster than a CGPDFPageRef

  • Use NSOperations or GCD & Blocks to prepare pages ahead
    of time.

  • call CGContextSetInterpolationQuality(ctx, kCGInterpolationHigh); CGContextSetRenderingIntent(ctx, kCGRenderingIntentDefault); before CGContextDrawPDFPage to reduce memory usage while drawing

  • init’ing your NSOperations with a docRef is a bad idea (memory), wrap the docRef into a singleton.

  • Cancel needless NSOperations When you can, especially if they will be using memory, beware of leaving contexts open though!

  • Recycle page objects and destroy unused views

  • Close any open Contexts as soon as you don’t need them

  • on receiving memory warnings release and reload the DocRef and any page Caches

Other PDF Features:

  • Getting Links inside a PDF (and here and here)

    • Understanding the PDF Rect for link positioning

    • Converting PDF annot datestrings

    • Getting the target of the link (Getting the page number from the /Dest array)

  • Getting a table of contents

  • Document title and Keywords

  • Getting Raw Text (and here and Here and here (positioning focused))

  • Searching(and here) (doesn’t work with all PDFs (some just show weird characters, I guess it’s an encoding issue but I’m not sure) -Credit BrainFeeder)

  • CALayer and Off-Screen Rendering – render the next page for fast/smooth display

Documentation

  • Quartz PDFObjects (Used for meta info, annotations, thumbs)
  • Abobe PDF Spec

Example projects

  • Apple/ ZoomingPDF – zooming, UIScrollView, CATiledLayer
  • vfr/ reader – zooming, paging, UIScrollView, CATiledView
  • brow/ leaves – paging with nice transitions
  • / skim – everything it seems (PDF reader/editor for OSX)

3 Answers
3

Leave a Comment