Merge pull request #1737 from zaczh/master

Making image downloading cache policy more clearer
This commit is contained in:
Bogdan Poplauschi 2017-03-10 12:40:26 +02:00
commit ad9f1a2436
3 changed files with 19 additions and 15 deletions

View File

@ -23,14 +23,14 @@ typedef NS_OPTIONS(NSUInteger, SDWebImageDownloaderOptions) {
/** /**
* Call completion block with nil image/imageData if the image was read from NSURLCache * Call completion block with nil image/imageData if the image was read from NSURLCache
* (to be combined with `SDWebImageDownloaderUseNSURLCache`). * (to be combined with `SDWebImageDownloaderUseNSURLCache`).
* I think this option should be renamed to 'SDWebImageDownloaderUsingCachedResponseDontLoad'
*/ */
SDWebImageDownloaderIgnoreCachedResponse = 1 << 3, SDWebImageDownloaderIgnoreCachedResponse = 1 << 3,
/** /**
* In iOS 4+, continue the download of the image if the app goes to background. This is achieved by asking the system for * In iOS 4+, continue the download of the image if the app goes to background. This is achieved by asking the system for
* extra time in background to let the request finish. If the background task expires the operation will be cancelled. * extra time in background to let the request finish. If the background task expires the operation will be cancelled.
*/ */
SDWebImageDownloaderContinueInBackground = 1 << 4, SDWebImageDownloaderContinueInBackground = 1 << 4,
/** /**

View File

@ -153,7 +153,17 @@
} }
// In order to prevent from potential duplicate caching (NSURLCache + SDImageCache) we disable the cache for image requests if told otherwise // In order to prevent from potential duplicate caching (NSURLCache + SDImageCache) we disable the cache for image requests if told otherwise
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url cachePolicy:(options & SDWebImageDownloaderUseNSURLCache ? NSURLRequestUseProtocolCachePolicy : NSURLRequestReloadIgnoringLocalCacheData) timeoutInterval:timeoutInterval]; NSURLRequestCachePolicy cachePolicy = NSURLRequestReloadIgnoringLocalCacheData;
if (options & SDWebImageDownloaderUseNSURLCache) {
if (options & SDWebImageDownloaderIgnoreCachedResponse) {
cachePolicy = NSURLRequestReturnCacheDataDontLoad;
} else {
cachePolicy = NSURLRequestUseProtocolCachePolicy;
}
}
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url cachePolicy:cachePolicy timeoutInterval:timeoutInterval];
request.HTTPShouldHandleCookies = (options & SDWebImageDownloaderHandleCookies); request.HTTPShouldHandleCookies = (options & SDWebImageDownloaderHandleCookies);
request.HTTPShouldUsePipelining = YES; request.HTTPShouldUsePipelining = YES;
if (sself.headersFilter) { if (sself.headersFilter) {

View File

@ -52,7 +52,6 @@ typedef NSMutableDictionary<NSString *, id> SDCallbacksDictionary;
#if SD_UIKIT || SD_WATCH #if SD_UIKIT || SD_WATCH
UIImageOrientation orientation; UIImageOrientation orientation;
#endif #endif
BOOL responseFromCached;
} }
@synthesize executing = _executing; @synthesize executing = _executing;
@ -74,7 +73,6 @@ typedef NSMutableDictionary<NSString *, id> SDCallbacksDictionary;
_finished = NO; _finished = NO;
_expectedSize = 0; _expectedSize = 0;
_unownedSession = session; _unownedSession = session;
responseFromCached = YES; // Initially wrong until `- URLSession:dataTask:willCacheResponse:completionHandler: is called or not called
_barrierQueue = dispatch_queue_create("com.hackemist.SDWebImageDownloaderOperationBarrierQueue", DISPATCH_QUEUE_CONCURRENT); _barrierQueue = dispatch_queue_create("com.hackemist.SDWebImageDownloaderOperationBarrierQueue", DISPATCH_QUEUE_CONCURRENT);
} }
return self; return self;
@ -386,8 +384,7 @@ didReceiveResponse:(NSURLResponse *)response
dataTask:(NSURLSessionDataTask *)dataTask dataTask:(NSURLSessionDataTask *)dataTask
willCacheResponse:(NSCachedURLResponse *)proposedResponse willCacheResponse:(NSCachedURLResponse *)proposedResponse
completionHandler:(void (^)(NSCachedURLResponse *cachedResponse))completionHandler { completionHandler:(void (^)(NSCachedURLResponse *cachedResponse))completionHandler {
responseFromCached = NO; // If this method is called, it means the response wasn't read from cache
NSCachedURLResponse *cachedResponse = proposedResponse; NSCachedURLResponse *cachedResponse = proposedResponse;
if (self.request.cachePolicy == NSURLRequestReloadIgnoringLocalCacheData) { if (self.request.cachePolicy == NSURLRequestReloadIgnoringLocalCacheData) {
@ -417,15 +414,12 @@ didReceiveResponse:(NSURLResponse *)response
} else { } else {
if ([self callbacksForKey:kCompletedCallbackKey].count > 0) { if ([self callbacksForKey:kCompletedCallbackKey].count > 0) {
/** /**
* See #1608 and #1623 - apparently, there is a race condition on `NSURLCache` that causes a crash * If you specified to use `NSURLCache`, then the response you get here is what you need.
* Limited the calls to `cachedResponseForRequest:` only for cases where we should ignore the cached response * if you specified to only use cached data via `SDWebImageDownloaderIgnoreCachedResponse`,
* and images for which responseFromCached is YES (only the ones that cannot be cached). * the response data will be nil.
* Note: responseFromCached is set to NO inside `willCacheResponse:`. This method doesn't get called for large images or images behind authentication * So we don't need to check the cache option here, since the system will obey the cache option
*/ */
if (self.options & SDWebImageDownloaderIgnoreCachedResponse && responseFromCached && [[NSURLCache sharedURLCache] cachedResponseForRequest:self.request]) { if (self.imageData) {
// hack
[self callCompletionBlocksWithImage:nil imageData:nil error:nil finished:YES];
} else if (self.imageData) {
UIImage *image = [UIImage sd_imageWithData:self.imageData]; UIImage *image = [UIImage sd_imageWithData:self.imageData];
NSString *key = [[SDWebImageManager sharedManager] cacheKeyForURL:self.request.URL]; NSString *key = [[SDWebImageManager sharedManager] cacheKeyForURL:self.request.URL];
image = [self scaledImageForKey:key image:image]; image = [self scaledImageForKey:key image:image];