Na iPhonie wykonuję żądanie HTTP przy użyciu NSURLRequest dla fragmentu danych. Alokacja obiektów gwałtownie rośnie i odpowiednio przypisuję dane. Kiedy skończę z danymi, odpowiednio je zwalniam - jednak instrumenty nie pokazują żadnych danych, które zostały zwolnione!
Moja teoria jest taka, że domyślnie żądania HTTP są buforowane - nie chcę, aby moja aplikacja na iPhone'a buforowała te dane.
Czy istnieje sposób na wyczyszczenie tej pamięci podręcznej po żądaniu lub zapobieżenie buforowaniu jakichkolwiek danych?
Próbowałem użyć wszystkich zasad pamięci podręcznej udokumentowanych trochę jak poniżej:
NSMutableURLRequest *theRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]];
theRequest.cachePolicy = NSURLRequestReloadIgnoringLocalCacheData;
ale wydaje się, że nic nie zwalnia pamięci!
cocoa-touch
caching
Nick Cartwright
źródło
źródło
Odpowiedzi:
Zwykle łatwiej jest utworzyć takie żądanie
NSURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:60.0];
Następnie utwórz połączenie
NSURLConnection *conn = [NSURLConnection connectionWithRequest:request delegate:self];
i zaimplementuj połączenie: willCacheResponse: metoda na delegacie. Zwrócenie zera powinno to zrobić.
- (NSCachedURLResponse *)connection:(NSURLConnection *)connection willCacheResponse:(NSCachedURLResponse *)cachedResponse { return nil; }
źródło
NSURLRequestReloadIgnoringCacheData
i wdrożenieconnection:willCacheResponse:
?connection:willCacheResponse:
pozwala nie przechowywać odpowiedzi w pamięci podręcznej.NSURLRequestReloadIgnoringCacheData
określa, że połączenie powinno ładować żądanie bez sprawdzania pamięci podręcznej. Przypuszczalnie ta pierwsza pomaga zarządzać alokacją pamięci.Mam ten sam problem w mojej aplikacji, gdy poprosiłem o informacje z Twittera. W moim przypadku nie musiałem zachowywać tych poświadczeń, więc po prostu kasuję je za pomocą następnego kodu:
- (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]; } }
Mam nadzieję, że u kogoś to zadziała :)
źródło
Jeśli używasz NSURLConnection, spójrz na delegata:
- (NSCachedURLResponse *)connection:(NSURLConnection *)connection willCacheResponse:(NSCachedURLResponse *)cachedResponse
Wartość zwracana
Rzeczywista odpowiedź z pamięci podręcznej do zapisania w pamięci podręcznej. Delegat może zwrócić niezmodyfikowaną odpowiedź cachedResponse, zwrócić zmodyfikowaną odpowiedź w pamięci podręcznej lub zwrócić wartość nil, jeśli żadna buforowana odpowiedź nie powinna być przechowywana dla połączenia.
źródło
Jeśli używasz
NSURLSession
, innym rozwiązaniem, aby zapobiec zapisywaniu żądań i parametrów do systemuCache.db
iOS tworzonego w katalogu aplikacjiCaches
, jest ustawienieNSURLCache
konfiguracji sesji na pamięć o rozmiarze 0 i pamięć podręczną dysku o rozmiarze 0, np.let configuration = URLSessionConfiguration.default configuration.urlCache = URLCache(memoryCapacity: 0, diskCapacity: 0, diskPath: nil) let session = URLSession(configuration: configuration)
lub, jak wspomniano powyżej, ustawiono na globalnym poziomie pamięci podręcznej
URLCache.shared = URLCache(memoryCapacity: 0, diskCapacity: 0, diskPath: nil)
Prawdopodobnie jest to 0 dla rozmiaru dysku, który zatrzymuje zapisywanie na dysku przez iOS, ale jeśli masz zasady
reloadIgnoringLocalCacheData
, prawdopodobnie nie jesteś zainteresowany buforowaniem pamięci.Uwaga Zapobiegnie to tworzeniu jakichkolwiek
Caches/Cache.db
(żądań i odpowiedzi) lubCaches/fsCachedData/
folderów (dane odpowiedzi). Zdecydowaliśmy się zastosować to podejście w aplikacji ze względów bezpieczeństwa, ponieważ nie chcemy, aby nasze żądania były nigdy przechowywane w pamięci podręcznej dysku.Jeśli ktoś wie, czy istnieje sposób, aby zatrzymać buforowanie tylko żądań, ale zachować buforowanie danych odpowiedzi z mechanizmu ładowania adresu URL iOS, chciałbym wiedzieć. (nie ma API ani oficjalnej dokumentacji na ten temat z tego, co mogę powiedzieć)
źródło
Jeśli nie jest to specyficzne dla pojedynczego żądania (chcesz wyłączyć pamięć podręczną dla całej aplikacji), poniżej jedna jest najlepszą opcją.Dodaj ten kod w delegacie aplikacji lub w oparciu o potrzeby w dowolnym miejscu
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];
źródło
NSMutableURLRequest* request = [[NSMutableURLRequest alloc] url]; [request setValue:@"no-store" forHTTPHeaderField:@"Cache-Control"]; [request setCachePolicy:NSURLRequestReloadIgnoringLocalCacheData];
Zakładając, że serwer jest poprawnie zaimplementowany, umieszczenie
Cache-Control:no-store
nagłówka w żądaniu wygeneruje odpowiedź serwera z takim samym nagłówkiem, co spowoduje,NSURLCache
że dane odpowiedzi nie zostaną zapisane na dysku.Dlatego nie ma potrzeby stosowania metody strzelby polegającej na wyłączaniu
NSURLCache
buforowania dysku.PS: Dodanie nagłówka powinno działać dla wszystkich frameworków HTTP, takich jak
AFNetworking
źródło