CALayer and Off-Screen Rendering

2019-01-22 23:08发布

问题:

I have a Paging UIScrollView with a contentSize large enough to hold a number of small UIScrollViews for zooming, The viewForZoomingInScrollView is a viewController that holds a CALayer for drawing a PDF page onto. This allows me to navigate through a PDF much like the ibooks PDF reader.

The code that draws the PDF (Tiled Layers) is located in:

- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx;

And simply adding a 'page' to the visible screen calls this method automatically. When I change page there is some delay before all the tiles are drawn, even though the object (page) has already been created.

What i want to be able to do is render the next page before the user scrolls to it, thus preventing the visible tiling effect. However, i have found that if the layer is located offscreen adding it to the scrollview doesn't call the drawLayer.

Any Ideas/common gotchas here?

I have tried:

[viewController.view.layer setNeedsLayout]; 
[viewController.view.layer setNeedsDisplay];

NB: The fact that this is replicating the ibooks functionally is irrelevant within the context of the full app.

回答1:

As i mentioned above, CALayers don't render if they are offscreen.

I ended up not drawing the PDF directly to the layer but instead, rendered the PDF page to an image when i needed (renders 1 page plus and minus one of the focused page)

Here is the render code:

-(UIImage *)renderPDFPageToImage:(int)pageNumber//NSOPERATION?
{
 //you may not want to permanently (app life) retain doc ref

 CGSize size = CGSizeMake(x,y);     
 UIGraphicsBeginImageContext(size);
 CGContextRef context = UIGraphicsGetCurrentContext();

 CGContextTranslateCTM(context, 0, 750);
 CGContextScaleCTM(context, 1.0, -1.0);

 CGPDFPageRef page;  //Move to class member 

    page = CGPDFDocumentGetPage (myDocumentRef, pageNumber);
    CGContextDrawPDFPage (context, page);

 UIImage * pdfImage = UIGraphicsGetImageFromCurrentImageContext();//autoreleased
 UIGraphicsEndImageContext();
 return pdfImage;

}