|
|
@@ -17,7 +17,7 @@ NSString *const SDWebImageDownloadReceiveResponseNotification = @"SDWebImageDown
|
|
|
NSString *const SDWebImageDownloadStopNotification = @"SDWebImageDownloadStopNotification";
|
|
|
NSString *const SDWebImageDownloadFinishNotification = @"SDWebImageDownloadFinishNotification";
|
|
|
|
|
|
-@interface SDWebImageDownloaderOperation () <NSURLSessionTaskDelegate>
|
|
|
+@interface SDWebImageDownloaderOperation ()
|
|
|
|
|
|
@property (copy, nonatomic) SDWebImageDownloaderProgressBlock progressBlock;
|
|
|
@property (copy, nonatomic) SDWebImageDownloaderCompletedBlock completedBlock;
|
|
|
@@ -27,8 +27,13 @@ NSString *const SDWebImageDownloadFinishNotification = @"SDWebImageDownloadFinis
|
|
|
@property (assign, nonatomic, getter = isFinished) BOOL finished;
|
|
|
@property (strong, nonatomic) NSMutableData *imageData;
|
|
|
|
|
|
-@property (strong, nonatomic) NSURLSession *session;
|
|
|
-@property (strong, nonatomic) NSURLSessionDataTask *dataTask;
|
|
|
+// This is weak because it is injected by whoever manages this session. If this gets nil-ed out, we won't be able to run
|
|
|
+// the task associated with this operation
|
|
|
+@property (weak, nonatomic) NSURLSession *unownedSession;
|
|
|
+// This is set if we're using not using an injected NSURLSession. We're responsible of invalidating this one
|
|
|
+@property (strong, nonatomic) NSURLSession *ownedSession;
|
|
|
+
|
|
|
+@property (strong, nonatomic, readwrite) NSURLSessionTask *dataTask;
|
|
|
|
|
|
@property (strong, atomic) NSThread *thread;
|
|
|
|
|
|
@@ -52,6 +57,21 @@ NSString *const SDWebImageDownloadFinishNotification = @"SDWebImageDownloadFinis
|
|
|
progress:(SDWebImageDownloaderProgressBlock)progressBlock
|
|
|
completed:(SDWebImageDownloaderCompletedBlock)completedBlock
|
|
|
cancelled:(SDWebImageNoParamsBlock)cancelBlock {
|
|
|
+
|
|
|
+ return [self initWithRequest:request
|
|
|
+ inSession:nil
|
|
|
+ options:options
|
|
|
+ progress:progressBlock
|
|
|
+ completed:completedBlock
|
|
|
+ cancelled:cancelBlock];
|
|
|
+}
|
|
|
+
|
|
|
+- (id)initWithRequest:(NSURLRequest *)request
|
|
|
+ inSession:(NSURLSession *)session
|
|
|
+ options:(SDWebImageDownloaderOptions)options
|
|
|
+ progress:(SDWebImageDownloaderProgressBlock)progressBlock
|
|
|
+ completed:(SDWebImageDownloaderCompletedBlock)completedBlock
|
|
|
+ cancelled:(SDWebImageNoParamsBlock)cancelBlock {
|
|
|
if ((self = [super init])) {
|
|
|
_request = request;
|
|
|
_shouldDecompressImages = YES;
|
|
|
@@ -62,6 +82,7 @@ NSString *const SDWebImageDownloadFinishNotification = @"SDWebImageDownloadFinis
|
|
|
_executing = NO;
|
|
|
_finished = NO;
|
|
|
_expectedSize = 0;
|
|
|
+ _unownedSession = session;
|
|
|
responseFromCached = YES; // Initially wrong until `- URLSession:dataTask:willCacheResponse:completionHandler: is called or not called
|
|
|
}
|
|
|
return self;
|
|
|
@@ -93,20 +114,24 @@ NSString *const SDWebImageDownloadFinishNotification = @"SDWebImageDownloadFinis
|
|
|
}];
|
|
|
}
|
|
|
#endif
|
|
|
- NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
|
|
|
- sessionConfig.timeoutIntervalForRequest = 15;
|
|
|
-
|
|
|
- /**
|
|
|
- * Create the session for this task
|
|
|
- * We send nil as delegate queue so that the session creates a serial operation queue for performing all delegate
|
|
|
- * method calls and completion handler calls.
|
|
|
- */
|
|
|
- self.session = [NSURLSession sessionWithConfiguration:sessionConfig
|
|
|
- delegate:self
|
|
|
- delegateQueue:nil];
|
|
|
+ NSURLSession *session = self.unownedSession;
|
|
|
+ if (!self.unownedSession) {
|
|
|
+ NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
|
|
|
+ sessionConfig.timeoutIntervalForRequest = 15;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Create the session for this task
|
|
|
+ * We send nil as delegate queue so that the session creates a serial operation queue for performing all delegate
|
|
|
+ * method calls and completion handler calls.
|
|
|
+ */
|
|
|
+ self.ownedSession = [NSURLSession sessionWithConfiguration:sessionConfig
|
|
|
+ delegate:self
|
|
|
+ delegateQueue:nil];
|
|
|
+ session = self.ownedSession;
|
|
|
+ }
|
|
|
|
|
|
+ self.dataTask = [session dataTaskWithRequest:self.request];
|
|
|
self.executing = YES;
|
|
|
- self.dataTask = [self.session dataTaskWithRequest:self.request];
|
|
|
self.thread = [NSThread currentThread];
|
|
|
}
|
|
|
|
|
|
@@ -188,8 +213,10 @@ NSString *const SDWebImageDownloadFinishNotification = @"SDWebImageDownloadFinis
|
|
|
self.dataTask = nil;
|
|
|
self.imageData = nil;
|
|
|
self.thread = nil;
|
|
|
- [self.session invalidateAndCancel];
|
|
|
- self.session = nil;
|
|
|
+ if (self.ownedSession) {
|
|
|
+ [self.ownedSession invalidateAndCancel];
|
|
|
+ self.ownedSession = nil;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- (void)setFinished:(BOOL)finished {
|
|
|
@@ -208,7 +235,7 @@ NSString *const SDWebImageDownloadFinishNotification = @"SDWebImageDownloadFinis
|
|
|
return YES;
|
|
|
}
|
|
|
|
|
|
-#pragma mark NSURLSessionTaskDelegate
|
|
|
+#pragma mark NSURLSessionDataDelegate
|
|
|
|
|
|
- (void)URLSession:(NSURLSession *)session
|
|
|
dataTask:(NSURLSessionDataTask *)dataTask
|
|
|
@@ -339,32 +366,24 @@ didReceiveResponse:(NSURLResponse *)response
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-+ (UIImageOrientation)orientationFromPropertyValue:(NSInteger)value {
|
|
|
- switch (value) {
|
|
|
- case 1:
|
|
|
- return UIImageOrientationUp;
|
|
|
- case 3:
|
|
|
- return UIImageOrientationDown;
|
|
|
- case 8:
|
|
|
- return UIImageOrientationLeft;
|
|
|
- case 6:
|
|
|
- return UIImageOrientationRight;
|
|
|
- case 2:
|
|
|
- return UIImageOrientationUpMirrored;
|
|
|
- case 4:
|
|
|
- return UIImageOrientationDownMirrored;
|
|
|
- case 5:
|
|
|
- return UIImageOrientationLeftMirrored;
|
|
|
- case 7:
|
|
|
- return UIImageOrientationRightMirrored;
|
|
|
- default:
|
|
|
- return UIImageOrientationUp;
|
|
|
+- (void)URLSession:(NSURLSession *)session
|
|
|
+ dataTask:(NSURLSessionDataTask *)dataTask
|
|
|
+ willCacheResponse:(NSCachedURLResponse *)proposedResponse
|
|
|
+ completionHandler:(void (^)(NSCachedURLResponse *cachedResponse))completionHandler {
|
|
|
+
|
|
|
+ responseFromCached = NO; // If this method is called, it means the response wasn't read from cache
|
|
|
+ NSCachedURLResponse *cachedResponse = proposedResponse;
|
|
|
+
|
|
|
+ if (self.request.cachePolicy == NSURLRequestReloadIgnoringLocalCacheData) {
|
|
|
+ // Prevents caching of responses
|
|
|
+ cachedResponse = nil;
|
|
|
+ }
|
|
|
+ if (completionHandler) {
|
|
|
+ completionHandler(cachedResponse);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-- (UIImage *)scaledImageForKey:(NSString *)key image:(UIImage *)image {
|
|
|
- return SDScaledImageForKey(key, image);
|
|
|
-}
|
|
|
+#pragma mark NSURLSessionTaskDelegate
|
|
|
|
|
|
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {
|
|
|
@synchronized(self) {
|
|
|
@@ -419,32 +438,7 @@ didReceiveResponse:(NSURLResponse *)response
|
|
|
[self done];
|
|
|
}
|
|
|
|
|
|
-- (void)URLSession:(NSURLSession *)session
|
|
|
- dataTask:(NSURLSessionDataTask *)dataTask
|
|
|
- willCacheResponse:(NSCachedURLResponse *)proposedResponse
|
|
|
- completionHandler:(void (^)(NSCachedURLResponse *cachedResponse))completionHandler {
|
|
|
-
|
|
|
- responseFromCached = NO; // If this method is called, it means the response wasn't read from cache
|
|
|
- NSCachedURLResponse *cachedResponse = proposedResponse;
|
|
|
-
|
|
|
- if (self.request.cachePolicy == NSURLRequestReloadIgnoringLocalCacheData) {
|
|
|
- // Prevents caching of responses
|
|
|
- cachedResponse = nil;
|
|
|
- }
|
|
|
- if (completionHandler) {
|
|
|
- completionHandler(cachedResponse);
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-- (BOOL)shouldContinueWhenAppEntersBackground {
|
|
|
- return self.options & SDWebImageDownloaderContinueInBackground;
|
|
|
-}
|
|
|
-
|
|
|
-- (void)URLSession:(NSURLSession *)session
|
|
|
- task:(NSURLSessionTask *)task
|
|
|
-didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge
|
|
|
- completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition,
|
|
|
- NSURLCredential *credential))completionHandler {
|
|
|
+- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler {
|
|
|
|
|
|
NSURLSessionAuthChallengeDisposition disposition = NSURLSessionAuthChallengePerformDefaultHandling;
|
|
|
__block NSURLCredential *credential = nil;
|
|
|
@@ -474,4 +468,37 @@ didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+#pragma mark Helper methods
|
|
|
+
|
|
|
++ (UIImageOrientation)orientationFromPropertyValue:(NSInteger)value {
|
|
|
+ switch (value) {
|
|
|
+ case 1:
|
|
|
+ return UIImageOrientationUp;
|
|
|
+ case 3:
|
|
|
+ return UIImageOrientationDown;
|
|
|
+ case 8:
|
|
|
+ return UIImageOrientationLeft;
|
|
|
+ case 6:
|
|
|
+ return UIImageOrientationRight;
|
|
|
+ case 2:
|
|
|
+ return UIImageOrientationUpMirrored;
|
|
|
+ case 4:
|
|
|
+ return UIImageOrientationDownMirrored;
|
|
|
+ case 5:
|
|
|
+ return UIImageOrientationLeftMirrored;
|
|
|
+ case 7:
|
|
|
+ return UIImageOrientationRightMirrored;
|
|
|
+ default:
|
|
|
+ return UIImageOrientationUp;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+- (UIImage *)scaledImageForKey:(NSString *)key image:(UIImage *)image {
|
|
|
+ return SDScaledImageForKey(key, image);
|
|
|
+}
|
|
|
+
|
|
|
+- (BOOL)shouldContinueWhenAppEntersBackground {
|
|
|
+ return self.options & SDWebImageDownloaderContinueInBackground;
|
|
|
+}
|
|
|
+
|
|
|
@end
|