When I analyze my app with Instruments, I found out that data allocated by CGContextDrawPDFPage
is not released immediately. App getting crash because of CGContextDrawPDFPage
.
Hello here is my code for drawing pdf in CATiledlayer
- (void)drawLayer:(CATiledLayer *)layer inContext:(CGContextRef)context
{
if (_PDFPageRef == nil) {
return;
}
CGPDFPageRef drawPDFPageRef = NULL;
CGPDFDocumentRef drawPDFDocRef = NULL;
@synchronized(self) // Briefly block main thread
{
drawPDFDocRef = CGPDFDocumentRetain(_PDFDocRef);
if( _PDFPageRef != (__bridge CGPDFPageRef)([NSNull null]) )
drawPDFPageRef = CGPDFPageRetain(_PDFPageRef);
else
return;
}
//CGContextSetRGBFillColor(context, 0.0f, 0.0f, 0.0f, 0.0f);
//CGContextFillRect(context, CGContextGetClipBoundingBox(context));
if (drawPDFPageRef != NULL) // Render the page into the context
{
CGFloat boundsHeight = viewBounds.size.height;
if (CGPDFPageGetRotationAngle(drawPDFPageRef) == 0)
{
CGFloat boundsWidth = viewBounds.size.width;
CGRect cropBox = CGPDFPageGetBoxRect(drawPDFPageRef, kCGPDFCropBox);
int pageRotation = CGPDFPageGetRotationAngle(drawPDFPageRef);
CGSize pageVisibleSize = CGSizeMake(cropBox.size.width, cropBox.size.height);
if ((pageRotation == 90) || (pageRotation == 270) ||(pageRotation == -90)) {
pageVisibleSize = CGSizeMake(cropBox.size.height, cropBox.size.width);
}
float scaleX = boundsWidth / pageVisibleSize.width;
float scaleY = boundsHeight / pageVisibleSize.height;
float scale = scaleX < scaleY ? scaleX : scaleY;
// Offset relative to top left corner of rectangle where the page will be displayed
float offsetX = 0;
float offsetY = 0;
float rectangleAspectRatio = boundsWidth / boundsHeight;
float pageAspectRatio = pageVisibleSize.width / pageVisibleSize.height;
if (pageAspectRatio < rectangleAspectRatio) {
// The page is narrower than the rectangle, we place it at center on the horizontal
offsetX = (boundsWidth - pageVisibleSize.width * scale) / 2;
}
else {
// The page is wider than the rectangle, we place it at center on the vertical
offsetY = (boundsHeight - pageVisibleSize.height * scale) / 2;
}
CGPoint point = CGPointMake(offsetX, offsetY);
//CGRect cropBox = CGPDFPageGetBoxRect(drawPDFPageRef, kCGPDFCropBox);
int rotate = CGPDFPageGetRotationAngle(drawPDFPageRef);
//CGContextSaveGState(context);
// Setup the coordinate system.
// Top left corner of the displayed page must be located at the point specified by the 'point' parameter.
CGContextTranslateCTM(context, point.x, point.y);
// Scale the page to desired zoom level.
CGContextScaleCTM(context, scale , scale);
// The coordinate system must be set to match the PDF coordinate system.
switch (rotate) {
case 0:
CGContextTranslateCTM(context, 0, cropBox.size.height);
CGContextScaleCTM(context, 1, -1);
break;
case 90:
CGContextScaleCTM(context, 1, -1);
CGContextRotateCTM(context, -M_PI / 2);
break;
case 180:
case -180:
CGContextScaleCTM(context, 1, -1);
CGContextTranslateCTM(context, cropBox.size.width, 0);
CGContextRotateCTM(context, M_PI);
break;
case 270:
case -90:
CGContextTranslateCTM(context, cropBox.size.height, cropBox.size.width);
CGContextRotateCTM(context, M_PI / 2);
CGContextScaleCTM(context, -1, 1);
break;
}
// The CropBox defines the page visible area, clip everything outside it.
CGRect clipRect = CGRectMake(0, 0, cropBox.size.width, cropBox.size.height);
CGContextAddRect(context, clipRect);
CGContextClip(context);
CGContextSetRGBFillColor(context, 1.0, 1.0, 1.0, 1.0);
CGContextFillRect(context, clipRect);
CGContextTranslateCTM(context, -cropBox.origin.x, -cropBox.origin.y);
CGContextSetInterpolationQuality(context, kCGInterpolationHigh);
// CGContextSetInterpolationQuality(context, kCGInterpolationMedium);
CGContextSetRenderingIntent(context, kCGRenderingIntentDefault);
if(context != nil && context != (__bridge CGContextRef)([NSNull null]))
{
CGContextDrawPDFPage(context, drawPDFPageRef);
//CGContextRestoreGState(context);
}
}
else // Use CGPDFPageGetDrawingTransform for pages with rotation (AKA kludge)
{
CGContextTranslateCTM(context, 0.0f, boundsHeight); CGContextScaleCTM(context, 1.0f, -1.0f);
CGContextConcatCTM(context, CGPDFPageGetDrawingTransform(drawPDFPageRef, kCGPDFCropBox, viewBounds, 0, true));
}
//CGContextDrawPDFPage(context, drawPDFPageRef);
}
CGPDFPageRelease(drawPDFPageRef); // Cleanup
CGPDFDocumentRelease(drawPDFDocRef);
}
This is by design. To allow faster re-draws, the CGPDFDocumentRef caches page resources.
The only way to empty this cache is to release and re-open the CGPDFDocumentRef.