So I work on a very large and very old legacy project that was coded about 5 years ago in non-ARC objective c code. I took over from the previous developers and now have to maintain this beast.
The app allows users to read PDF pages that are downloaded as separate files. The problem is the view where the PDFs are displayed on the screen is leaking memory badly. Simple paging for about 5 minutes results in about 400 megs of memory consumed.
So when profiling the app I discovered the line of code that seems to be the issue. The previous developer even left a comment: "TODO DANNY leak here 100%"... Thanks Danny...
Anyway I have tried many things and for the life of me can't understand why this is leaking memory. Most of my work and experience is with ARC projects so I am struggling to understand why this code is leaking.
The UIView subview class looks as follows:
- (void)dealloc {
self.pauseDraw = YES;
CGPDFPageRelease(pdfPage);
CGPDFDocumentRelease(pdfDocumentRef);
[super dealloc];
}
- (id)initWithFrame:(CGRect)frame andScale:(CGFloat)scale{
if ((self = [super initWithFrame:frame])) {
CATiledLayer *tiledLayer = (CATiledLayer *)[self layer];
if ([[[UIDevice currentDevice] modelName] isEqualToString:@"iPad 3G"]) {
tiledLayer.tileSize = CGSizeMake(1024, 1024);
tiledLayer.levelsOfDetail = 4;
tiledLayer.levelsOfDetailBias = 4;
} else {
tiledLayer.levelsOfDetail = 4;
tiledLayer.levelsOfDetailBias = 4;
tiledLayer.tileSize = CGSizeMake(2048, 2048);
}
myScale = scale;
}
return self;
}
+ (Class)layerClass {
return [CATiledLayer class];
}
- (void)setPage:(CGPDFPageRef)newPage andDocument:(CGPDFDocumentRef)docRef {
CGPDFPageRelease(pdfPage);
CGPDFDocumentRelease(pdfDocumentRef);
self->pdfPage = CGPDFPageRetain(newPage);
self->pdfDocumentRef = CGPDFDocumentRetain(docRef);
}
- (void) releasePDFsFromMemory {
CGPDFPageRelease(pdfPage);
CGPDFDocumentRelease(pdfDocumentRef);
}
-(void)drawRect:(CGRect)r {}
-(void)drawLayer:(CALayer*)layer inContext:(CGContextRef)context {
if(!self.superview){
return;
}
if (pauseDraw) {
return;
}
@autoreleasepool {
CGRect cropBox = CGPDFPageGetBoxRect(pdfPage, kCGPDFCropBox);
int rotate = CGPDFPageGetRotationAngle(pdfPage);
CGContextSaveGState(context);
CGContextTranslateCTM(context, 0, 0);
CGContextScaleCTM(context, myScale, myScale);
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:
self.frame = CGRectMake(0, 0, 768, 1004);
CGContextTranslateCTM(context, cropBox.size.height, cropBox.size.width);
CGContextRotateCTM(context, M_PI / 2);
CGContextScaleCTM(context, -1, 1);
break;
}
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);
CGContextSetRenderingIntent(context, kCGRenderingIntentDefault);
// TODO DANNY leak here 100% ->
CGContextDrawPDFPage(context, pdfPage);
CGContextRestoreGState(context);
}
}
Any help will be much appreciated!
Thanks in advance, Eish