2009-03-08 6 views
21

Ich benutze die Klasse NSURLConnection, um eine große Datei in meiner iPhone-Anwendung herunterzuladen, aber es stürzt immer wieder ab, weil es zu viel Speicher verbraucht. Ich mache die übliche NSURLConnection Verwendung, um die empfangenen Daten an ein NSMutableData Objekt anzufügen.Wie kann ich eine große Datei mit dem iPhone SDK herunterladen und Speicherprobleme vermeiden?

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { 
    [self.fileData appendData:data]; 
} 

Dann, nachdem ich die ganze Datei Abschluss des Downloads, ich spare es zu einer lokalen temporären Datei, und als kartiert Datei wie folgt lesen:

- (void)connectionDidFinishLoading:(NSURLConnection *)connection { 
    // save the downloaded data into a temporary file 
    NSString *tempPath = NSTemporaryDirectory(); 
    NSString *tempFile = [tempPath stringByAppendingPathComponent:@"temp.pdf"]; 
    [self.fileData writeToFile:tempFile atomically:YES]; 
    NSData *mappedData = [NSData dataWithContentsOfMappedFile:tempFile]; 

    NSURL *baseURL = [NSURL URLWithString:@"http://mydomain.com"]; 
    [webView loadData:mappedData MIMEType:@"application/pdf" textEncodingName:@"UTF-8" baseURL:baseURL]; 
} 

Was kann ich hier verbessern, diese zu vermeiden Speicherbelegungsprobleme?

+1

mit schrieb ich eine Bibliothek für das, ich bin es hier setzen gehofft, dass es für einige Leute nützlich sein wird, oder sie inspirieren, ihre eigene Lösung zu schreiben. Wenn Sie damit natürlich einverstanden sind. https://github.com/thibaultCha/TCBlobDownload – thibaultcha

Antwort

17

Wenn es so groß ist, warum nicht in die Datei schreiben, wie sie kommt, anstatt sie in einem NSData-Objekt zu behalten?

+1

jpm: Sie möchten die NSFileHandle-Klasse auschecken. –

+0

Ben, du hast vollkommen recht. Rewrote meine Klasse mit 'NSFileHandle', um zu vermeiden, die ganze Datei im Speicher zu halten, und scheint jetzt viel besser zu arbeiten. Danke Daniel für den Tipp auch! – jpm

6

ich bin

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data 
{ 
    filename = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:save_name]; 
    NSFileHandle *file1 = [NSFileHandle fileHandleForUpdatingAtPath: filename]; 
    [file1 writeData: data]; 
    [file1 closeFile]; 
} 
40
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse*)response { 

    filename = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:save_name]; // filename is in .h file 

    [[NSFileManager defaultManager] createFileAtPath:filename contents:nil attributes:nil]; 
     file = 
[[NSFileHandle fileHandleForUpdatingAtPath:filename] retain];// file is in .h 

//if (file)  { 
// 
//  [file seekToEndOfFile]; 
// } 
} 

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSD 
ata *)data { 

if (file) { 

     [file seekToEndOfFile]; 

    } [file writeData:data]; 

} 

- (void)connectionDidFinishLoading:(NSURLConnection*)connection { 

[file closeFile]; 

} 
+1

Es funktioniert wie ein Charme dank – objectivecdeveloper

+0

Gibt es Nachteile bei der Verwendung der einfacheren didReceiveData() unten von Mobihunterz gepostet? Scheint einfach und sauber. – drfence

+0

DRFENCE Das didReceiveData() ist gut, aber es öffnet und schließt die bestimmte Datei 'Datei1' jedes Mal, wenn diese Funktion aufgerufen wird. Und die Funktion wird beim Herunterladen größerer Dateien mehrmals aufgerufen. Daher kann die Ausführung aufgrund des Overheads von Öffnen/Schließen jedes Mal ein wenig langsam sein. Während die obige Funktion nur in die Datei schreibt, öffnet und schließt sie die Datei nur am Anfang und am Ende. –

Verwandte Themen