因此,我研究了一个非常大且非常古老的遗留项目,该项目大约在5年前以非ARC目标c代码编码。我接替了以前的开发人员,现在必须维护这个野兽。
该应用程序允许用户阅读作为单独文件下载的PDF页面。问题是在屏幕上显示PDF的视图正在严重泄漏内存。大约5分钟的简单分页会导致大约400兆的内存消耗。
因此,在分析应用程序时,我发现了似乎是问题的代码行。之前的开发人员甚至发表评论:" TODO DANNY在这里泄漏100%" ...谢谢Danny ......
无论如何,我已经尝试了很多东西,因为我的生活无法理解为什么这会泄漏记忆。我的大多数工作和经验都是针对ARC项目的,所以我很难理解为什么这个代码会泄漏。
UIView子视图类如下所示:
- (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);
}
}
非常感谢任何帮助!
提前致谢, EISH
答案 0 :(得分:1)
所以我设法解决了这个问题。
问题不在于我上面粘贴的代码(道歉是误导),问题是在父视图的dealloc方法中,前一个开发人员没有从superview中删除tilesPDF视图而没有设置调用release后变量为nil。
我通过在dealloc方法中放置一个NSLog并看到父视图正在释放来发现这一点,但是2个平铺的PDF子视图根本没有解除分配。
从超级视图中删除它们并将变量设置为nil后,两个dealloc方法都被触发,并且当你翻页时,应用程序内存使用量不会永久上升!