У меня есть тестовое приложение, и оно успешно загружает контент из сети, даже если пользователь переключает приложения во время загрузки. Отлично, теперь у меня есть фоновые загрузки. Теперь я хочу добавить кеширование. Мне нет смысла загружать изображения более одного раза из-за дизайна системы, учитывая 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?
}
Что вы думаете о моих правках выше? Почему я не вижу, чтобы файл возвращался очень быстро при последующих запросах?
Как я могу подтвердить, что файл обслуживается из кеша по второму запросу?