Ist es möglich zu verhindern, dass eine NSURLRequest Daten zwischenspeichert oder zwischengespeicherte Daten nach einer Anforderung entfernt?

89

Auf dem iPhone führe ich eine HTTP-Anforderung mit NSURLRequest für einen Datenblock aus. Objektzuordnungsspitzen und ich ordne die Daten entsprechend zu. Wenn ich mit den Daten fertig bin, gebe ich sie entsprechend frei - Instrumente zeigen jedoch keine Daten an, die freigegeben wurden!

Meine Theorie ist jedoch, dass HTTP-Anforderungen standardmäßig zwischengespeichert werden. Ich möchte nicht, dass meine iPhone-App diese Daten zwischenspeichert.

Gibt es eine Möglichkeit, diesen Cache nach einer Anforderung zu löschen oder zu verhindern, dass Daten überhaupt zwischengespeichert werden?

Ich habe versucht, alle Cache-Richtlinien zu verwenden, die wie folgt dokumentiert sind:

NSMutableURLRequest *theRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]];
theRequest.cachePolicy = NSURLRequestReloadIgnoringLocalCacheData;

aber nichts scheint die Erinnerung freizugeben!

Nick Cartwright
quelle
Wäre es möglich, dass es nicht mit dem Cache zusammenhängt? Haben Sie versucht, die Daten zu überprüfen, um festzustellen, ob es sich bei den Daten, die neu geladen werden sollten, tatsächlich um die alten handelt? Vielleicht kommt dein Lauch von woanders her. Wie initialisiere und befreie ich die NSURLRequests? Dies kann hilfreich sein, um das Problem zu diagnostizieren.
lpfavreau
Zu Ihrer Information - Wenn Sie die Dateien mit brutaler Gewalt entfernen möchten, gibt es hier einen Beispielcode: salesforce.stackexchange.com/a/69736
zekel

Antworten:

157

Normalerweise ist es einfacher, die Anfrage so zu erstellen

NSURLRequest *request = [NSURLRequest requestWithURL:url
      cachePolicy:NSURLRequestReloadIgnoringCacheData
      timeoutInterval:60.0];

Dann stellen Sie die Verbindung her

NSURLConnection *conn = [NSURLConnection connectionWithRequest:request
       delegate:self];

und implementieren Sie die Methode connection: willCacheResponse: auf dem Delegaten. Nur Null zurückzugeben sollte es tun.

- (NSCachedURLResponse *)connection:(NSURLConnection *)connection willCacheResponse:(NSCachedURLResponse *)cachedResponse {
  return nil;
}
tcurdt
quelle
Vielen Dank hier für Ihre Hilfe! Nick.
Nick Cartwright
1
Vielen Dank für diese Idee - ich habe wiederholt einen SOAP-Webdienst wie diesen angerufen und der Heap wuchs unkontrolliert, obwohl Lecks nicht zeigten, dass etwas nicht stimmte. Ich habe tagelang optimiert und schließlich versucht, das Caching zu verhindern, da viele CFURL * -Objekte aus dem internen Framework herumhingen. Die Rückgabe von null von willCacheResponse war das einzige, was funktioniert hat!
Bron Davies
15
Warum ist es notwendig, beides zu tun NSURLRequestReloadIgnoringCacheData und umzusetzen connection:willCacheResponse:?
Fabb
1
Hallo, ist es möglich, dass ich dies zum Laden lokaler Inhalte verwenden kann? Das Obige ist für NSUrlConnection, aber ich lade lokale HTML-Daten mit NSUrlRequest in UIWebView. Ich muss jegliches Caching ablehnen, da Bilder von SQLite in die Webansicht gelangen und der Speicher mit jedem Laden der Seite zunimmt. Vielen Dank.
Jim
7
@fabb, beim Überschreiben connection:willCacheResponse:können Sie die Antwort nicht im Cache speichern. NSURLRequestReloadIgnoringCacheDataGibt an, dass die Verbindung die Anforderung laden soll, ohne den Cache zu überprüfen. Ersteres hilft vermutlich bei der Verwaltung der Speicherzuordnung.
Christopher Pickslay
12

Ich habe das gleiche Problem in meiner App, als ich Informationen von Twitter angefordert habe. In meinem Fall musste ich diese Anmeldeinformationen nicht beibehalten, daher lösche ich sie einfach mit dem nächsten Code:

- (void) eraseCredentials{
NSURLCredentialStorage *credentialsStorage = [NSURLCredentialStorage sharedCredentialStorage];
NSDictionary *allCredentials = [credentialsStorage allCredentials];

//iterate through all credentials to find the twitter host
for (NSURLProtectionSpace *protectionSpace in allCredentials)
    if ([[protectionSpace host] isEqualToString:@"twitter.com"]){
        //to get the twitter's credentials
        NSDictionary *credentials = [credentialsStorage credentialsForProtectionSpace:protectionSpace];
        //iterate through twitter's credentials, and erase them all
        for (NSString *credentialKey in credentials)
            [credentialsStorage removeCredential:[credentials objectForKey:credentialKey] forProtectionSpace:protectionSpace];
    }
}

Ich hoffe es funktioniert für jemanden :)


quelle
Dies war eine perfekte Lösung für mein Problem, ich hatte ein erneutes Anmeldeproblem, da die Anmeldeinformationen gespeichert wurden und automatisch von der NSURLConnection übermittelt wurden. Vielen Dank, das hat mir sehr geholfen :)
RVN
Vielen Dank, es ist Arbeit für mich, ich bin wirklich dankbar für Ihren Vorschlag. Eigentlich ist mein Problem, dass NSURLRequest Benutzername und Passwort speichert. Also diese Hilfe, um Benutzeranmeldeinformationen aus dem Cache zu entfernen ...
Nilesh Kikani
10

Wenn Sie NSURLConnection verwenden, sehen Sie sich den Delegaten an:

- (NSCachedURLResponse *)connection:(NSURLConnection *)connection willCacheResponse:(NSCachedURLResponse *)cachedResponse

Rückgabewert

Die tatsächlich zwischengespeicherte Antwort, die im Cache gespeichert werden soll. Der Delegat kann cachedResponse unverändert zurückgeben, eine geänderte zwischengespeicherte Antwort zurückgeben oder nil zurückgeben, wenn für die Verbindung keine zwischengespeicherte Antwort gespeichert werden soll.

Catlan
quelle
Vielen Dank hier. Der Speicherbedarf meiner App hat sich plötzlich halbiert! Nick.
Nick Cartwright
9

Wenn Sie verwenden NSURLSession, besteht eine andere Lösung, um zu verhindern, dass Anforderungen und Parameter in das Cache.dbiOS- CachesVerzeichnis geschrieben werden, darin, NSURLCachedie Konfiguration für die Sitzung auf einen Speicher der Größe 0 und einen Festplatten-Cache der Größe 0 festzulegen, z

let configuration = URLSessionConfiguration.default    
configuration.urlCache = URLCache(memoryCapacity: 0, diskCapacity: 0, diskPath: nil)
let session = URLSession(configuration: configuration)

oder wie oben erwähnt auf globaler Cache-Ebene festgelegt

URLCache.shared = URLCache(memoryCapacity: 0, diskCapacity: 0, diskPath: nil)

Vermutlich ist es die 0 für die Festplattengröße, die das Schreiben von iOS auf die Festplatte stoppt. Wenn Sie jedoch eine Richtlinie dazu haben, sind reloadIgnoringLocalCacheDataSie wahrscheinlich auch nicht an Speicher-Caching interessiert.

Hinweis Dadurch wird verhindert, dass überhaupt Caches/Cache.db(Anforderungen und Antworten) oder Caches/fsCachedData/Ordner (Antwortdaten) erstellt werden. Wir haben uns aus Sicherheitsgründen für diesen Ansatz in einer App entschieden, da wir nicht möchten, dass unsere Anforderungen jemals im Festplatten-Cache gespeichert werden.

Wenn jemand weiß, dass es eine Möglichkeit gibt, nur das Zwischenspeichern von Anforderungen zu stoppen, aber das Zwischenspeichern von Antwortdaten über den Mechanismus zum Laden von iOS-URLs beizubehalten, würde mich das interessieren. (Es gibt keine API oder offizielle Dokumentation dazu, soweit ich das beurteilen kann)

Shagun Madhikarmi
quelle
7

Wenn dies nicht spezifisch für eine einzelne Anforderung ist (Sie möchten den Cache für die gesamte App deaktivieren), ist eine Option die beste. Fügen Sie diesen Code in den App-Delegaten ein oder basierend auf Ihren Anforderungen

        int cacheSizeMemory = 0*4*1024*1024; // 0MB
        int cacheSizeDisk = 0*32*1024*1024; // 0MB
        NSURLCache *sharedCache = [[NSURLCache alloc] initWithMemoryCapacity:cacheSizeMemory diskCapacity:cacheSizeDisk diskPath:@"nsurlcache"];
        [NSURLCache setSharedURLCache:sharedCache];
Sanjeev Rao
quelle
7
Funktioniert gut für mich, aber Sie können einfach 0 verwenden, anstatt die Multiplikation durchzuführen, die sowieso nur bei 0 endet.
Gary Riches
1
NSMutableURLRequest* request = [[NSMutableURLRequest alloc] url];
[request setValue:@"no-store" forHTTPHeaderField:@"Cache-Control"];
[request setCachePolicy:NSURLRequestReloadIgnoringLocalCacheData];

Unter der Annahme, dass der Server korrekt implementiert ist, Cache-Control:no-storegeneriert das Einfügen des Headers in die Anforderung eine Serverantwort mit demselben Header, wodurch NSURLCachedie Antwortdaten nicht auf der Festplatte gespeichert werden.

Daher ist der Shotgun-Ansatz zum Deaktivieren des NSURLCacheFestplatten-Caching nicht erforderlich .

PS: Das Hinzufügen des Headers sollte für alle HTTP-Frameworks funktionieren, wie z AFNetworking

Yuri Brigance
quelle