2014-10-03 4 views
7

Ich versuche, NSURLSessionDownloadTask zu verwenden, und nutzen Sie die integrierte URL-Caching-Funktion von Apple. Ich habe in immer das Caching gelungen, zu arbeiten, wenn ein NSURLSessionDataTask mit dem Code unter Verwendung von:Kann ich HTTP-Caching mit einer NSURLSessionDownloadTask auf iOS verwenden?

- (void)downloadUsingNSURLSessionDataTask:(NSURL *)url { 
    NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration]; 
    NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfig delegate:self delegateQueue:nil]; 
    NSURLRequest *request = [NSURLRequest requestWithURL:url]; 
    NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request]; 
    [dataTask resume]; 
} 

- (void)cachedDataTaskTest { 
    // This call performs an HTTP request 
    [self downloadUsingNSURLSessionDataTask:[NSURL URLWithString:@"http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"]]; 
    [NSThread sleepForTimeInterval:1]; 

    // This call returns the locally cached copy, and no HTTP request occurs 
    [self downloadUsingNSURLSessionDataTask:[NSURL URLWithString:@"http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"]]; 
} 

Ich brauche aber einen Hintergrund Download auszuführen, für die ich eine NSURLDownloadTask verwenden. Wenn ich auf dieses umschalte, tritt das Caching-Verhalten nicht auf.

- (void)downloadUsingNSURLSessionDownloadTask:(NSURL *)url { 
    NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration]; 
    NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfig delegate:self delegateQueue:nil]; 
    NSURLRequest *request = [NSURLRequest requestWithURL:url]; 
    NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithRequest:request]; 
    [downloadTask resume]; 
} 

- (void)cachedDownloadTaskTest { 
    // This call performs an HTTP request 
    [self downloadUsingNSURLSessionDownloadTask:[NSURL URLWithString:@"http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"]]; 
    [NSThread sleepForTimeInterval:1]; 

    // This call also performs an HTTP request 
    [self downloadUsingNSURLSessionDownloadTask:[NSURL URLWithString:@"http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"]]; 
} 

This documentation von Apple gibt an, dass NSURLDownloadTasks rufen Sie nicht die URLSession:dataTask:willCacheResponse:completionHandler: Delegatmethode, so ist es nicht möglich, für Ihre Anwendung in den Cache-Lebenszyklus haken. Meine Vermutung ist, dass dies bedeutet, dass Caching für diese Aufgaben einfach nicht verfügbar ist, aber es ist nicht explizit darüber.

  1. Für eine Daten Aufgabe, das NSURLSession Objekt ruft die URLSession:dataTask:willCacheResponse:completionHandler: Methode des Delegierten. Ihre App sollte dann entscheiden, ob Caching erlaubt. Wenn Sie diese Methode nicht implementieren, wird standardmäßig die im Konfigurationsobjekt der Sitzung angegebene Caching-Richtlinie verwendet.

Kann jemand diese Vermutung bestätigen, dass NSURLSessionDownloadTasks einfach nicht Caching unterstützen? Ist es möglich, das HTTP-Cache-Verhalten von Apple in einer Hintergrundaufgabe zu nutzen?

+0

Warum möchten Sie 'willCacheResponse' überschreiben? – quellish

+0

Ich möchte 'willCacheResponse' nicht überschreiben, aber ich habe bemerkt, dass Sie es nicht für NSURLDownloadTasks überschreiben können, und vermuten, dass dies darauf hinweist, dass diese Aufgaben Caching überhaupt nicht unterstützen. –

Antwort

8

NSURLSessionDownloadTask arbeitet mit einem Systemdienst (Daemon), der den Download außerhalb Ihres Anwendungsprozesses durchführt. Aus diesem Grund sind die Delegaten-Callbacks, die tatsächlich für eine Download-Task aufgerufen werden, eingeschränkter als die für NSURLSessionDataTask. Wie in Life Cycle of a URL Session dokumentiert, erhält ein Daten-Task-Delegat Callbacks, um das Caching-Verhalten anzupassen, während dies bei einem Download-Task-Delegaten nicht möglich ist.

Eine Download-Aufgabe sollte die Caching-Richtlinie verwenden, die von NSURLRequest angegeben wird, und sollte den Cache-Speicher verwenden, der von NSURLSessionConfiguration angegeben wird (falls dies nicht der Fall ist, melden Sie einen Fehler). Die Standard-Cache-Richtlinie lautet NSURLRequestUseProtocolCachePolicy, und der standardmäßige URL-Cache-Speicher ist der gemeinsame URL-Cache für nicht im Hintergrund und nicht ephemere Konfigurationen. Die Delegatenrückrufe für URLSession:dataTask:willCacheResponse:completionHandler: sind kein guter Indikator dafür, ob Caching tatsächlich stattfindet.

Wenn Sie eine NSURLSessionDownloadTask mit der Standardsitzungskonfiguration erstellen und die Cache-Richtlinie NSURLRequest s nicht anpassen, wird bereits Caching ausgeführt.

+0

Vielen Dank für Ihre Antwort. Ich finde, dass die 'NSURLRequestUseProtocolCachePolicy' in meinem' NSURLRequest' in einer 'NSURLSessionDownloadTask' nicht respektiert wird. Wenn ich das in einer Standalone-App reproduzieren kann, werde ich einen Bug-Report posten, wie Sie es vorgeschlagen haben. –

+0

Was ist das Verhalten, das Sie sehen? – quellish

+0

Ich habe ein Testskelett-Projekt erstellt, mit dem Sie Download- und Datenaufgaben auslösen können, während Sie den HTTP-Datenverkehr durch Charles überprüfen. Alle initialen 'NSURLSessionDownloadTask'-Anfragen machen HTTP-Anfragen, so dass kein Caching stattfindet. Die erste 'NSSessionDataTask' ruft eine Anfrage auf, aber alle nachfolgenden Anfragen eines beliebigen Typs rufen keine HTTP-Anfragen auf, da iOS die zwischengespeicherte Kopie verwendet. Im Wesentlichen wird die 'NSURLSessionDownloadTask' einen vorhandenen Cache verwenden, aber nicht hinzufügen. Sehen Sie das Projekt, um dies zu demonstrieren: https://github.com/nickstreet/CacheTest –

5

Es sieht aus wie NSURLSessionDownloadTask Cache nicht, von Design.

NSURLSessionConfiguration Dokumentation

Die defaultSessionConfiguration Methode dokumentiert ist:

Die Standardsitzungskonfiguration verwendet einen persistenten Disk-basierter Cache (außer wenn das Ergebnis in eine Datei heruntergeladen wird) und speichert Anmeldeinformationen im Schlüsselbund des Benutzers.

Keiner der anderen Konstruktoren ist jedoch so dokumentiert, dass die obige kursive Ausnahme ausgeschlossen wird. Ich habe auch backgroundSessionConfigurationWithIdentifier getestet und es scheint auch nicht die Aufgabe zu erledigen.

Auch requestCachePolicy bietet keinen Ausweg aus der Ausnahme.

NSURLSessionDownloadTask Laufzeiteffizienz

NSURLSessionDownloadTask schreibt eingehende Daten in eine temporäre Datei. Wenn die Datei abgeschlossen ist, benachrichtigt sie den Delegaten oder den Beendigungshandler. Schließlich löscht es die Datei.

Während es am Ende die Datei einfach in den Cache verschieben konnte, musste es sich entweder mit dem Delegaten oder dem Abschlusshandler befassen, der die Datei änderte und somit seine gecachete Darstellung änderte, oder sogar die Datei an einen permanenten Speicherort verschoben kann nicht verfolgen.

Es könnte die Datei vor Benachrichtigung des Delegaten oder Abschluss-Handler kopieren, aber das wäre ineffizient für große Dateien.

Es könnte die Datei schreibgeschützt halten, scheint dies aber nicht auf iOS 8.0 zu tun.

Daher ist es unwahrscheinlich, dass das System Caching von Download-Aufgaben durchführen würde.

Umgehung

Ihre beste Wette ist NSURLSessionDataTask verwenden, dann, wenn der Delegierten URLSession:dataTask:didReceiveData: Methode aufgerufen wird, die eingehenden Daten zu Ihrer eigenen Datei anhängen. Das nächste Mal, wenn Sie NSURLSessionDataTask verwenden, erhalten Sie die zwischengespeicherten Daten in einem Aufruf von URLSession:dataTask:didReceiveData:.

Verwandte Themen