2010-10-14 4 views
3

La tâche: créer une image à partir d'un fichier PDF comme aperçu rapide pour mon PDF affiché avec le CATiledLayer (plus lent, plus haute résolution). Problème: Je reçois très rapidement un message d'erreur sur mon iPad "Avertissement de la mémoire reçue Niveau = 1" et peu après "Avertissement de la mémoire reçue Niveau = 2" ... puis l'application plante.iOS: Obtenir "Avertissement de la mémoire reçue" après l'utilisation de l'image créée à partir du PDF et utilisée comme arrière-plan

- (void) drawSinglePage:(CALayer *)layer inContext:(CGContextRef)ctx { 
    CGContextSaveGState(ctx); 
    CGContextSetRGBFillColor(ctx, 1.0, 1.0, 1.0, 1.0); 
    CGContextFillRect(ctx, CGContextGetClipBoundingBox(ctx)); 
    @synchronized(self) { 

     // Draw PDF for HighRes 
     CGPDFPageRef page = CGPDFDocumentGetPage(page1, 1); 
     CGRect pageRect = CGPDFPageGetBoxRect(page, kCGPDFCropBox); 
     CGFloat scaleRatio = 960/pageRect.size.height; 
     CGFloat yOffset = ((960-pageRect.size.height)/scaleRatio)+960; 

     CGContextTranslateCTM(ctx, -(layer.bounds.size.width-pageRect.size.width)/2, yOffset); 
     CGContextScaleCTM(ctx, scaleRatio, -scaleRatio); 
     CGContextConcatCTM(ctx, CGPDFPageGetDrawingTransform(page, kCGPDFCropBox, layer.bounds, 0, true)); 
     CGContextDrawPDFPage(ctx, page); 

     // Draw Background-Image as fast preview (PROBLEM HERE!!) 
     UIGraphicsBeginImageContext(layer.bounds.size); 
     CGContextRef context = UIGraphicsGetCurrentContext(); 

     CGContextSetRGBFillColor(context, 1.0, 1.0, 1.0, 1.0); 
     CGRect prob = CGContextGetClipBoundingBox(context); 
     CGContextFillRect(context, prob); 

     CGContextSaveGState(context); 
     CGContextSetInterpolationQuality(context, kCGInterpolationLow); 
     CGContextTranslateCTM(context, -(layer.bounds.size.width-pageRect.size.width)/2, yOffset); 
     CGContextScaleCTM(context, scaleRatio, -scaleRatio); 
     CGContextConcatCTM(context, CGPDFPageGetDrawingTransform(page, kCGPDFCropBox, CGRectMake(0.0, 0.0, layer.bounds.size.width, layer.bounds.size.height), 0, true)); 
     CGContextDrawPDFPage(context, page); 
     CGContextRestoreGState(context); 
     UIImage *back = UIGraphicsGetImageFromCurrentImageContext(); 
     NSData *jpegDataFile = UIImageJPEGRepresentation(back, 0.2f); 
     UIImage *smBack = [[UIImage alloc] initWithData:jpegDataFile];  
     UIGraphicsEndImageContext(); 

     // Now set the subview 
     UIImageView *backgroundImageView = [[UIImageView alloc] initWithImage:smBack]; 
     backgroundImageView.frame = CGRectMake(0.0, 0.0, smBack.size.width, smBack.size.height); 
     backgroundImageView.contentMode = UIViewContentModeTopLeft; 
     backgroundImageView.opaque = YES; 
     [self.view addSubview:backgroundImageView]; 
     [self.view sendSubviewToBack:backgroundImageView]; 
     [backgroundImageView release]; 

    } 
    CGContextRestoreGState(ctx); 
} 

}

Note: si je ne mets pas la vue de l'image de fond tout est ok - donc assez sûr que je dois sortir quelque chose, mais je tout essayé. En ce moment je n'ai aucune idée. Remarque: le "CGPDFDocumentRelease(page1)" sera appelé dans la fonction - (void)dealloc de ce ViewController.

Répondre

3

Je ne sais pas combien de fois votre méthode drawSinglePage:inContext: est appelée, mais elle créera une nouvelle vue d'image avec l'image à chaque fois sans y faire référence. Cela signifie qu'un second appel augmentera l'utilisation de la mémoire, alors qu'une seule image est visible. Par conséquent, si cette méthode est appelée plusieurs fois, vous devez soit réutiliser la vue d'image (définir imageView.image = nil), soit supprimer la vue d'image précédemment créée avant d'en créer une nouvelle. Ceci libèrera l'image déjà en mémoire qui pourrait empêcher un avertissement de mémoire pendant le dessin de la page. De plus, gardez à l'esprit que le dessin d'une page PDF peut faire grimper l'utilisation de la mémoire de plus de 20 mégaoctets à chaque fois. Donc, en fonction de la quantité de mémoire utilisée par votre application, cela seul pourrait provoquer l'avertissement de la mémoire. Réduisez l'utilisation de la mémoire et n'essayez pas de dessiner plus d'une page en même temps.

0

Regardez dans https://github.com/mindbrix/UIImage-PDF (BSD?), Ils font un bon travail dans le rendu d'un PDF dans un UIImage. Lorsque je regarde votre code, je vois que vous ne libérez pas le document CGPDF après le dessin. Notez que, selon le document, CGPDFDocument peut prendre une quantité considérable de mémoire, et la compression d'une image iPad rétine avec UIImageJPEGRepresentation nécessite également beaucoup de mémoire. Vous pouvez éviter cette pression mémoire si vous libérez tout votre contenu (CGPDFPage, CGPDFDocument) directement après le dessin.

Notez également que CGPDFDocument a un cache interne qui ne peut être effacé que s'il est détruit et recréé. Faites-le après avoir reçu un avertissement de mémoire, ou vous finirez par tomber en panne. (si le PDF est suffisamment complexe.)