2011-01-12 2 views
7

Für einen PDF-Reader möchte ich ein Dokument vorbereiten, indem Sie "Screenshots" von jeder Seite und speichern Sie sie auf der Festplatte. Erster Ansatz istWas (tf) sind die Geheimnisse hinter PDF-Speicherzuweisung (CGPDFDocumentRef)

CGPDFDocumentRef document = CGPDFDocumentCreateWithURL((CFURLRef) someURL); 
for (int i = 1; i<=pageCount; i++) 
{ 
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];  
    CGPDFPageRef page = CGPDFDocumentGetPage(document, i); 
    ...//getting + manipulating graphics context etc. 
    ... 
    CGContextDrawPDFPage(context, page); 
    ... 
    UIImage *resultingImage = UIGraphicsGetImageFromCurrentImageContext(); 
    ...//saving the image to disc 
    [pool drain]; 
} 
CGPDFDocumentRelease(document); 

Das in viel Speicher führt, die nach dem ersten Lauf der Schleife nicht freigegeben zu werden scheint (das erste Dokument in Vorbereitung), aber nicht mehr unreleased Speicher in Nachkauf:

MEMORY BEFORE:   6 MB 
MEMORY DURING 1ST DOC: 40 MB 
MEMORY AFTER 1ST DOC: 25 MB 
MEMORY DURING 2ND DOC: 40 MB 
MEMORY AFTER 2ND DOC: 25 MB 
.... 

Ändern Sie den Code zu

for (int i = 1; i<=pageCount; i++) 
{ 
    CGPDFDocumentRef document = CGPDFDocumentCreateWithURL((CFURLRef) someURL); 
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];  
    CGPDFPageRef page = CGPDFDocumentGetPage(document, i); 
    ...//getting + manipulating graphics context etc. 
    ... 
    CGContextDrawPDFPage(context, page); 
    ... 
    UIImage *resultingImage = UIGraphicsGetImageFromCurrentImageContext(); 
    ...//saving the image to disc 
    CGPDFDocumentRelease(document); 
    [pool drain]; 
} 

ändert die Speichernutzung zu

MEMORY BEFORE:   6 MB 
MEMORY DURING 1ST DOC: 9 MB 
MEMORY AFTER 1ST DOC: 7 MB 
MEMORY DURING 2ND DOC: 9 MB 
MEMORY AFTER 2ND DOC: 7 MB 
.... 

ist aber offensichtlich ein Rückschritt in der Leistung.

Wenn ich ein PDF (später, anderer Thread) im ersten Fall liest, wird kein Speicher mehr reserviert (bleib bei 25 MB), während im zweiten Fall Speicher bis zu 20 MB (von 7) geht.

In beiden Fällen, wenn ich den CGContextDrawPDFPage(context, page); Zeilenspeicher entfernen ist (fast) konstant bei 6 MB während und nach allen Vorbereitungen von Dokumenten.

Kann jemand erklären, was dort vor sich geht?

Antwort

4

CGPDFDocument Caches ziemlich aggressiv und Sie haben sehr wenig Kontrolle darüber, abgesehen von - wie Sie getan haben - das Dokument freigeben und von der Festplatte neu zu laden.

Der Grund dafür, dass beim Entfernen des CGContextDrawPDFPage-Aufrufs nicht viele Zuordnungen angezeigt werden, ist, dass Quartz die Seitenressourcen langsam lädt. Wenn Sie einfach CGPDFDocumentGetPage aufrufen, werden nur einige grundlegende Metadaten wie Begrenzungsrahmen und Anmerkungen geladen (sehr klein im Speicher).

Schriftarten, Bilder usw. werden nur geladen, wenn Sie die Seite tatsächlich zeichnen - aber sie werden dann relativ lange in einem internen Cache gespeichert. Dies soll das Rendering beschleunigen, da Seitenressourcen häufig auf mehrere Seiten verteilt werden. Außerdem ist es üblich, eine Seite mehrmals zu rendern (z. B. beim Heranzoomen). Sie werden bemerken, dass das Rendern einer Seite beim zweiten Mal wesentlich schneller ist.

+0

Danke, Sinn für mich, also habe ich es als "richtig" markiert, ohne es tatsächlich zu beweisen. –

+1

Hallo omz.Vielen Dank für die detaillierte Erklärung.Ich habe ein ähnliches Problem, die Speicherauslastung ist drastisch erhöht, wenn ich auf dem Rendern der Seiten und App stürzt nach einiger Zeit.Ich verwende separate PDFDocument für jede Seite (enthält nur eine Seite), die in drawLayer erstellt und freigegeben wird: inContext: method.please geben Sie mir einen Vorschlag, dieses automatische Caching des Seiteninhalts zu vermeiden und die Speichernutzung zu reduzieren. – Hariprasad

+0

@Hariprasad Ich habe ein kleines Problem mit dir. Und ich kann keine Lösungen finden. Manche sagen, es ist der Fehler des Frameworks, andere sind die Veröffentlichung, aber ich denke, dass meine Version alles veröffentlicht hat. Ich habe keine Lecks oder irgendetwas und stürze irgendwann noch ab. Haben Sie eine Lösung dafür gefunden? – otakuProgrammer

Verwandte Themen