Как кешировать с помощью NSURLSession и NSURLCache. Не работает
У меня есть тестовое приложение, и оно успешно загружает контент из сети, даже если пользователь переключает приложения во время загрузки. Отлично, теперь у меня есть фоновые загрузки. Теперь я хочу добавить кеширование. Нет смысла загружать изображения более одного раза, в том числе дизайн системы, учитывая URL изображения, я могу сказать, что содержимое этого URL никогда не изменится. Итак, теперь я хочу кешировать результаты своей загрузки, используя встроенный в память кэш / память на диске Apple, о котором я так много читал (в отличие от того, чтобы сохранить файл вручную в NSCachesDirectory и затем проверить его перед созданием нового просьба, ик). Впопытка чтобы кэширование работало поверх этого рабочего кода, я добавил следующий код:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
// Set app-wide shared cache (first number is megabyte value)
[NSURLCache setSharedURLCache:[[NSURLCache alloc] initWithMemoryCapacity:60 * 1024 * 1024
diskCapacity:200 * 1024 * 1024
diskPath:nil]];
return YES;
}
Когда я создаю свой сеанс, я добавил две новые строки (URLCache и requestCachePolicy).
// Helper method to get a single session object
- (NSURLSession *)backgroundSession
{
static NSURLSession *session = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration backgroundSessionConfiguration:@"com.example.apple-samplecode.SimpleBackgroundTransfer.BackgroundSession"];
configuration.URLCache = [NSURLCache sharedURLCache]; // NEW LINE ON TOP OF OTHERWISE WORKING CODE
configuration.requestCachePolicy = NSURLRequestReturnCacheDataElseLoad; // NEW LINE ON TOP OF OTHERWISE WORKING CODE
session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil];
});
return session;
}
Затем, чтобы быть лишним в попытке увидеть успех кэширования, я переключил мою строку NSURLRequest с
// NSURLRequest *request = [NSURLRequest requestWithURL:downloadURL]; // Old line, I've replaced this with...
NSURLRequest *request = [NSURLRequest requestWithURL:downloadURL cachePolicy:NSURLRequestReturnCacheDataElseLoad timeoutInterval:2*60]; // New line
Теперь, когда я иду, чтобы загрузить предмет во второй раз, опыт точно такой же, как и первый !! Загрузка занимает много времени, а индикатор выполнения анимирован медленно и устойчиво, как при первоначальной загрузке. Я хочу, чтобы данные в кеше немедленно !! Что мне не хватает ???
----------------------------ОБНОВИТЬ--------------------- -------
Хорошо, благодаря ответу Торстена, я добавил следующие две строки кода в свойdidFinishDownloadingToURL
метод делегата:
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)downloadURL {
// Added these lines...
NSLog(@"DiskCache: %@ of %@", @([[NSURLCache sharedURLCache] currentDiskUsage]), @([[NSURLCache sharedURLCache] diskCapacity]));
NSLog(@"MemoryCache: %@ of %@", @([[NSURLCache sharedURLCache] currentMemoryUsage]), @([[NSURLCache sharedURLCache] memoryCapacity]));
/*
OUTPUTS:
DiskCache: 4096 of 209715200
MemoryCache: 0 of 62914560
*/
}
Это замечательно. Это подтверждает, что кеш растет. Я предполагаю, что поскольку я использую downloadTask (загрузка в файл, а не в память), именно поэтому DiskCache растет, а не кэш-память в первую очередь? Я полагал, что все будет идти в кэш памяти, пока он не переполнится, а затем будет использоваться дисковый кэш, и, возможно, кэш памяти будет записан на диск, прежде чем ОС убьет приложение в фоновом режиме, чтобы освободить память. Я неправильно понимаю, как работает кэш Apple?
Это шаг вперед наверняка, но второй раз я скачиваю файлэто занимает столько же времени, сколько в первый раз (может быть, 10 секунд или около того), и следующий метод снова выполняется:
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
{
// This shouldn't execute the second time around should it? Even if this is supposed to get executed a second time around then shouldn't it be lightning fast? It's not.
// On all subsequent requests, it slowly iterates through the downloading of the content just as slow as the first time. No caching is apparent. What am I missing?
}
Что вы делаете из моих правок выше? Почему я не вижу, что файл возвращается очень быстро при последующих запросах?
Как я могу подтвердить, что файл подается из кеша на 2-й запрос?