Просмотр исходного кода

Move all download settings into SDWebImageDownloaderConfig, make it more easy to use with clear API.

Deprecate `createNewSessionWithConfiguration`, which make downloader not sync with URLSession. If user need to specify sharedDownloader config, just modify the defaultDownloaderConfig instead.
DreamPiggy 8 лет назад
Родитель
Сommit
c3892d7d08

+ 3 - 3
Examples/SDWebImage Demo/MasterViewController.m

@@ -56,8 +56,8 @@
         
         // HTTP NTLM auth example
         // Add your NTLM image url to the array below and replace the credentials
-        [SDWebImageManager sharedManager].imageDownloader.username = @"httpwatch";
-        [SDWebImageManager sharedManager].imageDownloader.password = @"httpwatch01";
+        [SDWebImageManager sharedManager].imageDownloader.config.username = @"httpwatch";
+        [SDWebImageManager sharedManager].imageDownloader.config.password = @"httpwatch01";
         
         self.objects = [NSMutableArray arrayWithObjects:
                     @"http://www.httpwatch.com/httpgallery/authentication/authenticatedimage/default.aspx?0.35786508303135633",     // requires HTTP auth, used to demo the NTLM auth
@@ -79,7 +79,7 @@
 
     }
     [SDWebImageManager.sharedManager.imageDownloader setValue:@"SDWebImage Demo" forHTTPHeaderField:@"AppName"];
-    SDWebImageManager.sharedManager.imageDownloader.executionOrder = SDWebImageDownloaderLIFOExecutionOrder;
+    SDWebImageManager.sharedManager.imageDownloader.config.executionOrder = SDWebImageDownloaderLIFOExecutionOrder;
     return self;
 }
 

+ 28 - 0
SDWebImage.xcodeproj/project.pbxproj

@@ -412,6 +412,18 @@
 		329A18621FFF5DFD008C9A2F /* UIImage+WebCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 329A18581FFF5DFD008C9A2F /* UIImage+WebCache.m */; };
 		329A18631FFF5DFD008C9A2F /* UIImage+WebCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 329A18581FFF5DFD008C9A2F /* UIImage+WebCache.m */; };
 		329A18641FFF5DFD008C9A2F /* UIImage+WebCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 329A18581FFF5DFD008C9A2F /* UIImage+WebCache.m */; };
+		32B9B537206ED4230026769D /* SDWebImageDownloaderConfig.h in Headers */ = {isa = PBXBuildFile; fileRef = 32B9B535206ED4230026769D /* SDWebImageDownloaderConfig.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		32B9B538206ED4230026769D /* SDWebImageDownloaderConfig.h in Headers */ = {isa = PBXBuildFile; fileRef = 32B9B535206ED4230026769D /* SDWebImageDownloaderConfig.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		32B9B539206ED4230026769D /* SDWebImageDownloaderConfig.h in Headers */ = {isa = PBXBuildFile; fileRef = 32B9B535206ED4230026769D /* SDWebImageDownloaderConfig.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		32B9B53A206ED4230026769D /* SDWebImageDownloaderConfig.h in Headers */ = {isa = PBXBuildFile; fileRef = 32B9B535206ED4230026769D /* SDWebImageDownloaderConfig.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		32B9B53B206ED4230026769D /* SDWebImageDownloaderConfig.h in Headers */ = {isa = PBXBuildFile; fileRef = 32B9B535206ED4230026769D /* SDWebImageDownloaderConfig.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		32B9B53C206ED4230026769D /* SDWebImageDownloaderConfig.h in Headers */ = {isa = PBXBuildFile; fileRef = 32B9B535206ED4230026769D /* SDWebImageDownloaderConfig.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		32B9B53D206ED4230026769D /* SDWebImageDownloaderConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = 32B9B536206ED4230026769D /* SDWebImageDownloaderConfig.m */; };
+		32B9B53E206ED4230026769D /* SDWebImageDownloaderConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = 32B9B536206ED4230026769D /* SDWebImageDownloaderConfig.m */; };
+		32B9B53F206ED4230026769D /* SDWebImageDownloaderConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = 32B9B536206ED4230026769D /* SDWebImageDownloaderConfig.m */; };
+		32B9B540206ED4230026769D /* SDWebImageDownloaderConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = 32B9B536206ED4230026769D /* SDWebImageDownloaderConfig.m */; };
+		32B9B541206ED4230026769D /* SDWebImageDownloaderConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = 32B9B536206ED4230026769D /* SDWebImageDownloaderConfig.m */; };
+		32B9B542206ED4230026769D /* SDWebImageDownloaderConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = 32B9B536206ED4230026769D /* SDWebImageDownloaderConfig.m */; };
 		32C0FDE12013426C001B8F2D /* SDWebImageIndicator.h in Headers */ = {isa = PBXBuildFile; fileRef = 32C0FDDF2013426C001B8F2D /* SDWebImageIndicator.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		32C0FDE22013426C001B8F2D /* SDWebImageIndicator.h in Headers */ = {isa = PBXBuildFile; fileRef = 32C0FDDF2013426C001B8F2D /* SDWebImageIndicator.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		32C0FDE32013426C001B8F2D /* SDWebImageIndicator.h in Headers */ = {isa = PBXBuildFile; fileRef = 32C0FDDF2013426C001B8F2D /* SDWebImageIndicator.h */; settings = {ATTRIBUTES = (Public, ); }; };
@@ -1472,6 +1484,8 @@
 		3290FA031FA478AF0047D20C /* SDWebImageFrame.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDWebImageFrame.m; sourceTree = "<group>"; };
 		329A18571FFF5DFD008C9A2F /* UIImage+WebCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "UIImage+WebCache.h"; path = "SDWebImage/UIImage+WebCache.h"; sourceTree = "<group>"; };
 		329A18581FFF5DFD008C9A2F /* UIImage+WebCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "UIImage+WebCache.m"; path = "SDWebImage/UIImage+WebCache.m"; sourceTree = "<group>"; };
+		32B9B535206ED4230026769D /* SDWebImageDownloaderConfig.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDWebImageDownloaderConfig.h; sourceTree = "<group>"; };
+		32B9B536206ED4230026769D /* SDWebImageDownloaderConfig.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDWebImageDownloaderConfig.m; sourceTree = "<group>"; };
 		32C0FDDF2013426C001B8F2D /* SDWebImageIndicator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDWebImageIndicator.h; sourceTree = "<group>"; };
 		32C0FDE02013426C001B8F2D /* SDWebImageIndicator.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDWebImageIndicator.m; sourceTree = "<group>"; };
 		32CF1C051FA496B000004BD1 /* SDWebImageCoderHelper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDWebImageCoderHelper.h; sourceTree = "<group>"; };
@@ -1968,6 +1982,8 @@
 				53922D8C148C56230056699D /* SDWebImageDownloader.m */,
 				530E49E316460AE2002868E7 /* SDWebImageDownloaderOperation.h */,
 				530E49E416460AE2002868E7 /* SDWebImageDownloaderOperation.m */,
+				32B9B535206ED4230026769D /* SDWebImageDownloaderConfig.h */,
+				32B9B536206ED4230026769D /* SDWebImageDownloaderConfig.m */,
 			);
 			name = Downloader;
 			sourceTree = "<group>";
@@ -2174,6 +2190,7 @@
 				323F8B531F38EF770092B609 /* backward_references_enc.h in Headers */,
 				4317395A1CDFC8B70008FEB9 /* mux_types.h in Headers */,
 				431739561CDFC8B70008FEB9 /* demux.h in Headers */,
+				32B9B53A206ED4230026769D /* SDWebImageDownloaderConfig.h in Headers */,
 				80377C4A1F2F666300F89830 /* bit_writer_utils.h in Headers */,
 				4397D2F81D0DF44200BB2784 /* MKAnnotationView+WebCache.h in Headers */,
 				323F8BE71F38EF770092B609 /* vp8li_enc.h in Headers */,
@@ -2264,6 +2281,7 @@
 				321E60B11F38E90100405457 /* SDWebImageWebPCoder.h in Headers */,
 				80377E9A1F2F66D400F89830 /* common_dec.h in Headers */,
 				327054D5206CD8B3006EA328 /* SDWebImageAPNGCoder.h in Headers */,
+				32B9B538206ED4230026769D /* SDWebImageDownloaderConfig.h in Headers */,
 				80377C231F2F666300F89830 /* quant_levels_utils.h in Headers */,
 				321E60BF1F38E91700405457 /* UIImage+ForceDecode.h in Headers */,
 				80377EA61F2F66D400F89830 /* webpi_dec.h in Headers */,
@@ -2405,6 +2423,7 @@
 				43A62A201D0E0A800089D7DD /* mux_types.h in Headers */,
 				43A62A211D0E0A800089D7DD /* types.h in Headers */,
 				80377C641F2F666400F89830 /* bit_writer_utils.h in Headers */,
+				32B9B53B206ED4230026769D /* SDWebImageDownloaderConfig.h in Headers */,
 				43A62A1E1D0E0A800089D7DD /* format_constants.h in Headers */,
 				80377E111F2F66A800F89830 /* lossless_common.h in Headers */,
 				431BB6F61D06D2C1006A3455 /* UIImage+MultiFormat.h in Headers */,
@@ -2435,6 +2454,7 @@
 				32F7C0892030719600873181 /* UIImage+Transform.h in Headers */,
 				80377EDA1F2F66D500F89830 /* common_dec.h in Headers */,
 				80377EE61F2F66D500F89830 /* webpi_dec.h in Headers */,
+				32B9B53C206ED4230026769D /* SDWebImageDownloaderConfig.h in Headers */,
 				4397D2BA1D0DDD8C00BB2784 /* demux.h in Headers */,
 				80377C8F1F2F666400F89830 /* rescaler_utils.h in Headers */,
 				4397D2BD1D0DDD8C00BB2784 /* types.h in Headers */,
@@ -2525,6 +2545,7 @@
 				323F8B521F38EF770092B609 /* backward_references_enc.h in Headers */,
 				4317394F1CDFC8B70008FEB9 /* demux.h in Headers */,
 				43CE757D1CFE9427006C64D0 /* FLAnimatedImageView.h in Headers */,
+				32B9B539206ED4230026769D /* SDWebImageDownloaderConfig.h in Headers */,
 				80377C301F2F666300F89830 /* bit_writer_utils.h in Headers */,
 				431739541CDFC8B70008FEB9 /* types.h in Headers */,
 				323F8BE61F38EF770092B609 /* vp8li_enc.h in Headers */,
@@ -2631,6 +2652,7 @@
 				80377D1D1F2F66A100F89830 /* yuv.h in Headers */,
 				43CE75D01CFE98E0006C64D0 /* FLAnimatedImageView+WebCache.h in Headers */,
 				807A12281F89636300EC2A9B /* SDWebImageCodersManager.h in Headers */,
+				32B9B537206ED4230026769D /* SDWebImageDownloaderConfig.h in Headers */,
 				80377C051F2F665300F89830 /* huffman_utils.h in Headers */,
 				80377E881F2F66D000F89830 /* alphai_dec.h in Headers */,
 				32484775201775F600AF9E5A /* SDAnimatedImage.h in Headers */,
@@ -2993,6 +3015,7 @@
 				80377EBE1F2F66D500F89830 /* quant_dec.c in Sources */,
 				80377DB61F2F66A700F89830 /* dec_clip_tables.c in Sources */,
 				80377C5E1F2F666300F89830 /* utils.c in Sources */,
+				32B9B540206ED4230026769D /* SDWebImageDownloaderConfig.m in Sources */,
 				323F8C0B1F38EF770092B609 /* muxedit.c in Sources */,
 				80377DC11F2F66A700F89830 /* enc_mips32.c in Sources */,
 				80377DBC1F2F66A700F89830 /* dec_sse41.c in Sources */,
@@ -3172,6 +3195,7 @@
 				3237F9EC20161AE000A88143 /* NSImage+Additions.m in Sources */,
 				4314D1411D0E0E3B004B36C9 /* SDWebImageDownloaderOperation.m in Sources */,
 				80377D561F2F66A700F89830 /* rescaler_neon.c in Sources */,
+				32B9B53E206ED4230026769D /* SDWebImageDownloaderConfig.m in Sources */,
 				32F7C0762030114C00873181 /* SDWebImageTransformer.m in Sources */,
 				80377D551F2F66A700F89830 /* rescaler_msa.c in Sources */,
 				80377D5E1F2F66A700F89830 /* yuv_mips_dsp_r2.c in Sources */,
@@ -3327,6 +3351,7 @@
 				3237F9EA20161AE000A88143 /* NSImage+Additions.m in Sources */,
 				431BB6B61D06D2C1006A3455 /* UIImage+WebP.m in Sources */,
 				80377E251F2F66A800F89830 /* rescaler_neon.c in Sources */,
+				32B9B541206ED4230026769D /* SDWebImageDownloaderConfig.m in Sources */,
 				32F7C0792030114C00873181 /* SDWebImageTransformer.m in Sources */,
 				80377E241F2F66A800F89830 /* rescaler_msa.c in Sources */,
 				80377E2D1F2F66A800F89830 /* yuv_mips_dsp_r2.c in Sources */,
@@ -3411,6 +3436,7 @@
 				3290FA0F1FA478AF0047D20C /* SDWebImageFrame.m in Sources */,
 				80377EE01F2F66D500F89830 /* vp8_dec.c in Sources */,
 				32CF1C121FA496B000004BD1 /* SDWebImageCoderHelper.m in Sources */,
+				32B9B542206ED4230026769D /* SDWebImageDownloaderConfig.m in Sources */,
 				80377E521F2F66A800F89830 /* filters_msa.c in Sources */,
 				329A18641FFF5DFD008C9A2F /* UIImage+WebCache.m in Sources */,
 				80377C821F2F666400F89830 /* filters_utils.c in Sources */,
@@ -3619,6 +3645,7 @@
 				80377EAE1F2F66D400F89830 /* quant_dec.c in Sources */,
 				80377D6E1F2F66A700F89830 /* cost_sse2.c in Sources */,
 				80377D991F2F66A700F89830 /* rescaler_mips32.c in Sources */,
+				32B9B53F206ED4230026769D /* SDWebImageDownloaderConfig.m in Sources */,
 				323F8C0A1F38EF770092B609 /* muxedit.c in Sources */,
 				80377D851F2F66A700F89830 /* filters_sse2.c in Sources */,
 				80377D711F2F66A700F89830 /* dec_clip_tables.c in Sources */,
@@ -3778,6 +3805,7 @@
 				80377CE41F2F66A100F89830 /* cost_sse2.c in Sources */,
 				80377D0F1F2F66A100F89830 /* rescaler_mips32.c in Sources */,
 				323F8C081F38EF770092B609 /* muxedit.c in Sources */,
+				32B9B53D206ED4230026769D /* SDWebImageDownloaderConfig.m in Sources */,
 				80377CFB1F2F66A100F89830 /* filters_sse2.c in Sources */,
 				80377CE71F2F66A100F89830 /* dec_clip_tables.c in Sources */,
 				43A9186B1D8308FE00B3925F /* SDImageCacheConfig.m in Sources */,

+ 20 - 81
SDWebImage/SDWebImageDownloader.h

@@ -10,6 +10,7 @@
 #import "SDWebImageCompat.h"
 #import "SDWebImageDefine.h"
 #import "SDWebImageOperation.h"
+#import "SDWebImageDownloaderConfig.h"
 
 typedef NS_OPTIONS(NSUInteger, SDWebImageDownloaderOptions) {
     /**
@@ -73,18 +74,6 @@ typedef NS_OPTIONS(NSUInteger, SDWebImageDownloaderOptions) {
     SDWebImageDownloaderPreloadAllFrames = 1 << 10
 };
 
-typedef NS_ENUM(NSInteger, SDWebImageDownloaderExecutionOrder) {
-    /**
-     * Default value. All download operations will execute in queue style (first-in-first-out).
-     */
-    SDWebImageDownloaderFIFOExecutionOrder,
-
-    /**
-     * All download operations will execute in stack style (last-in-first-out).
-     */
-    SDWebImageDownloaderLIFOExecutionOrder
-};
-
 FOUNDATION_EXPORT NSString * _Nonnull const SDWebImageDownloadStartNotification;
 FOUNDATION_EXPORT NSString * _Nonnull const SDWebImageDownloadStopNotification;
 
@@ -121,87 +110,47 @@ typedef SDHTTPHeadersDictionary * _Nullable (^SDWebImageDownloaderHeadersFilterB
 @interface SDWebImageDownloader : NSObject
 
 /**
- * Decompressing images that are downloaded and cached can improve performance but can consume lot of memory.
- * Defaults to YES. Set this to NO if you are experiencing a crash due to excessive memory consumption.
- */
-@property (assign, nonatomic) BOOL shouldDecompressImages;
-
-/**
- *  The maximum number of concurrent downloads
+ Downloader Config object - storing all kind of settings
  */
-@property (assign, nonatomic) NSInteger maxConcurrentDownloads;
+@property (nonatomic, copy, readonly, nonnull) SDWebImageDownloaderConfig *config;
 
 /**
- * Shows the current amount of downloads that still need to be downloaded
- */
-@property (readonly, nonatomic) NSUInteger currentDownloadCount;
-
-/**
- *  The timeout value (in seconds) for the download operation. Default: 15.0.
- */
-@property (assign, nonatomic) NSTimeInterval downloadTimeout;
-
-/**
- * The configuration in use by the internal NSURLSession.
- * Mutating this object directly has no effect.
+ * Set filter to pick headers for downloading image HTTP request.
  *
- * @see createNewSessionWithConfiguration:
+ * This block will be invoked for each downloading image request, returned
+ * NSDictionary will be used as headers in corresponding HTTP request.
  */
-@property (readonly, nonatomic, nonnull) NSURLSessionConfiguration *sessionConfiguration;
+@property (nonatomic, copy, nullable) SDWebImageDownloaderHeadersFilterBlock headersFilter;
 
 /**
- * Gets/Sets a subclass of `SDWebImageDownloaderOperation` as the default
- * `NSOperation` to be used each time SDWebImage constructs a request
- * operation to download an image.
- *
- * @note Passing `NSOperation<SDWebImageDownloaderOperationInterface>` to set as default. Passing `nil` will revert to `SDWebImageDownloaderOperation`.
+ * The configuration in use by the internal NSURLSession. If you want to provide a custom sessionConfiguration, use `SDWebImageDownloaderConfig.sessionConfiguration` and create a new downloader instance.
+ @note This is immutable according to NSURLSession's documentation. Mutating this object directly has no effect.
  */
-@property (assign, nonatomic, nullable) Class operationClass;
+@property (nonatomic, readonly, nonnull) NSURLSessionConfiguration *sessionConfiguration;
 
 /**
  * Gets/Sets the download queue suspension state.
  */
-@property (assign, nonatomic, getter=isSuspended) BOOL suspended;
+@property (nonatomic, assign, getter=isSuspended) BOOL suspended;
 
 /**
- * Changes download operations execution order. Default value is `SDWebImageDownloaderFIFOExecutionOrder`.
- */
-@property (assign, nonatomic) SDWebImageDownloaderExecutionOrder executionOrder;
-
-/**
- *  Set the default URL credential to be set for request operations.
- */
-@property (strong, nonatomic, nullable) NSURLCredential *urlCredential;
-
-/**
- * Set username
- */
-@property (strong, nonatomic, nullable) NSString *username;
-
-/**
- * Set password
- */
-@property (strong, nonatomic, nullable) NSString *password;
-
-/**
- * Set filter to pick headers for downloading image HTTP request.
- *
- * This block will be invoked for each downloading image request, returned
- * NSDictionary will be used as headers in corresponding HTTP request.
+ * Shows the current amount of downloads that still need to be downloaded
  */
-@property (nonatomic, copy, nullable) SDWebImageDownloaderHeadersFilterBlock headersFilter;
+@property (nonatomic, assign, readonly) NSUInteger currentDownloadCount;
 
 /**
- *  Returns the global shared downloader instance
+ *  Returns the global shared downloader instance. Which use the `SDWebImageDownloaderConfig.defaultDownloaderConfiguration` config.
  */
 @property (nonatomic, class, readonly, nonnull) SDWebImageDownloader *sharedDownloader;
 
 /**
- * Creates an instance of a downloader with specified session configuration.
- * @note `timeoutIntervalForRequest` is going to be overwritten.
- * @return new instance of downloader class
+ Creates an instance of a downloader with specified downloader config.
+ You can specify session configuration, timeout or operation class through downloader config.
+
+ @param config The downloader config. If you specify nil, the `defaultDownloaderConfig` will be used.
+ @return new instance of downloader class
  */
-- (nonnull instancetype)initWithSessionConfiguration:(nullable NSURLSessionConfiguration *)sessionConfiguration NS_DESIGNATED_INITIALIZER;
+- (nonnull instancetype)initWithConfig:(nullable SDWebImageDownloaderConfig *)config NS_DESIGNATED_INITIALIZER;
 
 /**
  * Set a value for a HTTP header to be appended to each download HTTP request.
@@ -279,16 +228,6 @@ typedef SDHTTPHeadersDictionary * _Nullable (^SDWebImageDownloaderHeadersFilterB
  */
 - (void)cancelAllDownloads;
 
-/**
- * Forces SDWebImageDownloader to create and use a new NSURLSession that is
- * initialized with the given configuration.
- * @note All existing download operations in the queue will be cancelled.
- * @note `timeoutIntervalForRequest` is going to be overwritten.
- *
- * @param sessionConfiguration The configuration to use for the new NSURLSession
- */
-- (void)createNewSessionWithConfiguration:(nonnull NSURLSessionConfiguration *)sessionConfiguration;
-
 /**
  * Invalidates the managed session, optionally canceling pending operations.
  * @note If you use custom downloader instead of the shared downloader, you need call this method when you do not use it to avoid memory leak

+ 45 - 61
SDWebImage/SDWebImageDownloader.m

@@ -7,6 +7,7 @@
  */
 
 #import "SDWebImageDownloader.h"
+#import "SDWebImageDownloaderConfig.h"
 #import "SDWebImageDownloaderOperation.h"
 
 #define LOCK(lock) dispatch_semaphore_wait(lock, DISPATCH_TIME_FOREVER);
@@ -14,7 +15,7 @@
 
 @interface SDWebImageDownloadToken ()
 
-@property (nonatomic, weak, nullable) NSOperation<SDWebImageDownloaderOperationInterface> *downloadOperation;
+@property (nonatomic, weak, nullable) NSOperation<SDWebImageDownloaderOperation> *downloadOperation;
 
 @end
 
@@ -81,14 +82,16 @@
 }
 
 - (nonnull instancetype)init {
-    return [self initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
+    return [self initWithConfig:SDWebImageDownloaderConfig.defaultDownloaderConfig];
 }
 
-- (nonnull instancetype)initWithSessionConfiguration:(nullable NSURLSessionConfiguration *)sessionConfiguration {
-    if ((self = [super init])) {
-        _operationClass = [SDWebImageDownloaderOperation class];
-        _shouldDecompressImages = YES;
-        _executionOrder = SDWebImageDownloaderFIFOExecutionOrder;
+- (instancetype)initWithConfig:(SDWebImageDownloaderConfig *)config {
+    self = [super init];
+    if (self) {
+        if (!config) {
+            config = SDWebImageDownloaderConfig.defaultDownloaderConfig;
+        }
+        _config = [config copy];
         _downloadQueue = [NSOperationQueue new];
         _downloadQueue.maxConcurrentOperationCount = 6;
         _downloadQueue.name = @"com.hackemist.SDWebImageDownloader";
@@ -100,30 +103,21 @@
 #endif
         _operationsLock = dispatch_semaphore_create(1);
         _headersLock = dispatch_semaphore_create(1);
-        _downloadTimeout = 15.0;
-
-        [self createNewSessionWithConfiguration:sessionConfiguration];
-    }
-    return self;
-}
-
-- (void)createNewSessionWithConfiguration:(NSURLSessionConfiguration *)sessionConfiguration {
-    [self cancelAllDownloads];
-
-    if (self.session) {
-        [self.session invalidateAndCancel];
-    }
-
-    sessionConfiguration.timeoutIntervalForRequest = self.downloadTimeout;
-
-    /**
-     *  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:sessionConfiguration
+        NSURLSessionConfiguration *sessionConfiguration = _config.sessionConfiguration;
+        if (!sessionConfiguration) {
+            sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
+        }
+        sessionConfiguration.timeoutIntervalForRequest = _config.downloadTimeout;
+        /**
+         *  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.
+         */
+        _session = [NSURLSession sessionWithConfiguration:sessionConfiguration
                                                  delegate:self
                                             delegateQueue:nil];
+    }
+    return self;
 }
 
 - (void)invalidateSessionAndCancel:(BOOL)cancelPendingOperations {
@@ -144,6 +138,10 @@
     [self.downloadQueue cancelAllOperations];
 }
 
+- (NSURLSessionConfiguration *)sessionConfiguration {
+    return self.session.configuration;
+}
+
 - (void)setValue:(nullable NSString *)value forHTTPHeaderField:(nullable NSString *)field {
     LOCK(self.headersLock);
     if (value) {
@@ -168,30 +166,6 @@
     return allHTTPHeaderFields;
 }
 
-- (void)setMaxConcurrentDownloads:(NSInteger)maxConcurrentDownloads {
-    _downloadQueue.maxConcurrentOperationCount = maxConcurrentDownloads;
-}
-
-- (NSUInteger)currentDownloadCount {
-    return _downloadQueue.operationCount;
-}
-
-- (NSInteger)maxConcurrentDownloads {
-    return _downloadQueue.maxConcurrentOperationCount;
-}
-
-- (NSURLSessionConfiguration *)sessionConfiguration {
-    return self.session.configuration;
-}
-
-- (void)setOperationClass:(nullable Class)operationClass {
-    if (operationClass && [operationClass isSubclassOfClass:[NSOperation class]] && [operationClass conformsToProtocol:@protocol(SDWebImageDownloaderOperationInterface)]) {
-        _operationClass = operationClass;
-    } else {
-        _operationClass = [SDWebImageDownloaderOperation class];
-    }
-}
-
 - (nullable SDWebImageDownloadToken *)downloadImageWithURL:(NSURL *)url options:(SDWebImageDownloaderOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageDownloaderCompletedBlock)completedBlock {
     return [self downloadImageWithURL:url options:options context:nil progress:progressBlock completed:completedBlock];
 }
@@ -205,7 +179,7 @@
 
     return [self addProgressCallback:progressBlock completedBlock:completedBlock forURL:url createCallback:^SDWebImageDownloaderOperation *{
         __strong __typeof (wself) sself = wself;
-        NSTimeInterval timeoutInterval = sself.downloadTimeout;
+        NSTimeInterval timeoutInterval = sself.config.downloadTimeout;
         if (timeoutInterval == 0.0) {
             timeoutInterval = 15.0;
         }
@@ -224,13 +198,19 @@
         else {
             request.allHTTPHeaderFields = [sself allHTTPHeaderFields];
         }
-        SDWebImageDownloaderOperation *operation = [[sself.operationClass alloc] initWithRequest:request inSession:sself.session options:options context:context];
-        operation.shouldDecompressImages = sself.shouldDecompressImages;
+        Class operationClass = sself.config.operationClass;
+        if (operationClass && [operationClass isSubclassOfClass:[NSOperation class]] && [operationClass conformsToProtocol:@protocol(SDWebImageDownloaderOperation)]) {
+            // Custom operation class
+        } else {
+            operationClass = [SDWebImageDownloaderOperation class];
+        }
+        SDWebImageDownloaderOperation *operation = [[operationClass alloc] initWithRequest:request inSession:sself.session options:options context:context];
+        operation.shouldDecompressImages = sself.config.shouldDecompressImages;
         
-        if (sself.urlCredential) {
-            operation.credential = sself.urlCredential;
-        } else if (sself.username && sself.password) {
-            operation.credential = [NSURLCredential credentialWithUser:sself.username password:sself.password persistence:NSURLCredentialPersistenceForSession];
+        if (sself.config.urlCredential) {
+            operation.credential = sself.config.urlCredential;
+        } else if (sself.config.username && sself.config.password) {
+            operation.credential = [NSURLCredential credentialWithUser:sself.config.username password:sself.config.password persistence:NSURLCredentialPersistenceForSession];
         }
         
         if (options & SDWebImageDownloaderHighPriority) {
@@ -239,7 +219,7 @@
             operation.queuePriority = NSOperationQueuePriorityLow;
         }
         
-        if (sself.executionOrder == SDWebImageDownloaderLIFOExecutionOrder) {
+        if (sself.config.executionOrder == SDWebImageDownloaderLIFOExecutionOrder) {
             // Emulate LIFO execution order by systematically adding new operations as last operation's dependency
             [sself.lastAddedOperation addDependency:operation];
             sself.lastAddedOperation = operation;
@@ -316,6 +296,10 @@
     self.downloadQueue.suspended = suspended;
 }
 
+- (NSUInteger)currentDownloadCount {
+    return self.downloadQueue.operationCount;
+}
+
 - (void)cancelAllDownloads {
     [self.downloadQueue cancelAllOperations];
 }

+ 81 - 0
SDWebImage/SDWebImageDownloaderConfig.h

@@ -0,0 +1,81 @@
+/*
+ * This file is part of the SDWebImage package.
+ * (c) Olivier Poitrey <rs@dailymotion.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+#import <Foundation/Foundation.h>
+#import "SDWebImageCompat.h"
+
+typedef NS_ENUM(NSInteger, SDWebImageDownloaderExecutionOrder) {
+    /**
+     * Default value. All download operations will execute in queue style (first-in-first-out).
+     */
+    SDWebImageDownloaderFIFOExecutionOrder,
+    
+    /**
+     * All download operations will execute in stack style (last-in-first-out).
+     */
+    SDWebImageDownloaderLIFOExecutionOrder
+};
+
+@interface SDWebImageDownloaderConfig : NSObject <NSCopying>
+
+/**
+ Gets/Sets the default downloader config.
+ */
+@property (nonatomic, class, nonnull) SDWebImageDownloaderConfig *defaultDownloaderConfig;
+
+/**
+ * Decompressing images that are downloaded and cached can improve performance but can consume lot of memory.
+ * Defaults to YES. Set this to NO if you are experiencing a crash due to excessive memory consumption.
+ */
+@property (nonatomic, assign) BOOL shouldDecompressImages;
+
+/**
+ *  The maximum number of concurrent downloads
+ */
+@property (nonatomic, assign) NSInteger maxConcurrentDownloads;
+
+/**
+ *  The timeout value (in seconds) for the download operation. Default: 15.0.
+ */
+@property (nonatomic, assign) NSTimeInterval downloadTimeout;
+
+/**
+ * The custom session configuration in use by NSURLSession.
+ */
+@property (nonatomic, strong, nonnull) NSURLSessionConfiguration *sessionConfiguration;
+
+/**
+ * Gets/Sets a subclass of `SDWebImageDownloaderOperation` as the default
+ * `NSOperation` to be used each time SDWebImage constructs a request
+ * operation to download an image.
+ *
+ * @note Passing `NSOperation<SDWebImageDownloaderOperation>` to set as default. Passing `nil` will revert to `SDWebImageDownloaderOperation`.
+ */
+@property (nonatomic, assign, nullable) Class operationClass;
+
+/**
+ * Changes download operations execution order. Default value is `SDWebImageDownloaderFIFOExecutionOrder`.
+ */
+@property (nonatomic, assign) SDWebImageDownloaderExecutionOrder executionOrder;
+
+/**
+ *  Set the default URL credential to be set for request operations.
+ */
+@property (nonatomic, strong, nullable) NSURLCredential *urlCredential;
+
+/**
+ * Set username
+ */
+@property (nonatomic, copy, nullable) NSString *username;
+
+/**
+ * Set password
+ */
+@property (nonatomic, copy, nullable) NSString *password;
+
+@end

+ 55 - 0
SDWebImage/SDWebImageDownloaderConfig.m

@@ -0,0 +1,55 @@
+/*
+ * This file is part of the SDWebImage package.
+ * (c) Olivier Poitrey <rs@dailymotion.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+#import "SDWebImageDownloaderConfig.h"
+
+static SDWebImageDownloaderConfig * _defaultDownloaderConfig;
+
+@implementation SDWebImageDownloaderConfig
+
++ (SDWebImageDownloaderConfig *)defaultDownloaderConfig {
+    if (!_defaultDownloaderConfig) {
+        _defaultDownloaderConfig = [SDWebImageDownloaderConfig new];
+    }
+    return _defaultDownloaderConfig;
+}
+
++ (void)setDefaultDownloaderConfig:(SDWebImageDownloaderConfig *)defaultDownloaderConfig {
+    if (defaultDownloaderConfig) {
+        _defaultDownloaderConfig = defaultDownloaderConfig;
+    }
+}
+
+- (instancetype)init {
+    self = [super init];
+    if (self) {
+        _shouldDecompressImages = YES;
+        _maxConcurrentDownloads = 3;
+        _downloadTimeout = 15.0;
+        _executionOrder = SDWebImageDownloaderFIFOExecutionOrder;
+    }
+    return self;
+}
+
+- (id)copyWithZone:(NSZone *)zone {
+    SDWebImageDownloaderConfig *config = [[[self class] allocWithZone:zone] init];
+    config.shouldDecompressImages = self.shouldDecompressImages;
+    config.maxConcurrentDownloads = self.maxConcurrentDownloads;
+    config.downloadTimeout = self.downloadTimeout;
+    config.sessionConfiguration = [self.sessionConfiguration copyWithZone:zone];
+    config.operationClass = self.operationClass;
+    config.executionOrder = self.executionOrder;
+    config.urlCredential = [self.urlCredential copyWithZone:zone];
+    config.username = [self.username copyWithZone:zone];
+    config.password = [self.password copyWithZone:zone];
+    
+    return config;
+}
+
+
+@end

+ 2 - 2
SDWebImage/SDWebImageDownloaderOperation.h

@@ -21,7 +21,7 @@ FOUNDATION_EXPORT NSString * _Nonnull const SDWebImageDownloadFinishNotification
  Describes a downloader operation. If one wants to use a custom downloader op, it needs to inherit from `NSOperation` and conform to this protocol
  For the description about these methods, see `SDWebImageDownloaderOperation`
  */
-@protocol SDWebImageDownloaderOperationInterface<NSObject>
+@protocol SDWebImageDownloaderOperation <NSObject>
 
 - (nonnull instancetype)initWithRequest:(nullable NSURLRequest *)request
                               inSession:(nullable NSURLSession *)session
@@ -46,7 +46,7 @@ FOUNDATION_EXPORT NSString * _Nonnull const SDWebImageDownloadFinishNotification
 @end
 
 
-@interface SDWebImageDownloaderOperation : NSOperation <SDWebImageDownloaderOperationInterface, SDWebImageOperation, NSURLSessionTaskDelegate, NSURLSessionDataDelegate>
+@interface SDWebImageDownloaderOperation : NSOperation <SDWebImageDownloaderOperation, NSURLSessionTaskDelegate, NSURLSessionDataDelegate>
 
 /**
  * The request used by the operation's task.

+ 15 - 15
Tests/Tests/SDWebImageDownloaderTests.m

@@ -28,7 +28,7 @@
 /**
  *  A class that fits the NSOperation+SDWebImageDownloaderOperationInterface requirement so we can test
  */
-@interface CustomDownloaderOperation : NSOperation<SDWebImageDownloaderOperationInterface>
+@interface CustomDownloaderOperation : NSOperation<SDWebImageDownloaderOperation>
 
 @property (nonatomic, assign) BOOL shouldDecompressImages;
 @property (nonatomic, strong, nullable) NSURLCredential *credential;
@@ -103,26 +103,26 @@
 }
 
 - (void)test05ThatSetAndGetMaxConcurrentDownloadsWorks {
-    NSInteger initialValue = [SDWebImageDownloader sharedDownloader].maxConcurrentDownloads;
+    NSInteger initialValue = SDWebImageDownloader.sharedDownloader.config.maxConcurrentDownloads;
     
-    [[SDWebImageDownloader sharedDownloader] setMaxConcurrentDownloads:3];
-    expect([SDWebImageDownloader sharedDownloader].maxConcurrentDownloads).to.equal(3);
+    SDWebImageDownloader.sharedDownloader.config.maxConcurrentDownloads = 3;
+    expect(SDWebImageDownloader.sharedDownloader.config.maxConcurrentDownloads).to.equal(3);
     
-    [[SDWebImageDownloader sharedDownloader] setMaxConcurrentDownloads:initialValue];
+    SDWebImageDownloader.sharedDownloader.config.maxConcurrentDownloads = initialValue;
 }
 
 - (void)test06ThatUsingACustomDownloaderOperationWorks {
     // we try to set a usual NSOperation as operation class. Should not work
-    [[SDWebImageDownloader sharedDownloader] setOperationClass:[NSOperation class]];
-    expect([SDWebImageDownloader sharedDownloader].operationClass).to.equal([SDWebImageDownloaderOperation class]);
+    SDWebImageDownloader.sharedDownloader.config.operationClass = [NSOperation class];
+    expect(SDWebImageDownloader.sharedDownloader.config.operationClass).to.equal([SDWebImageDownloaderOperation class]);
     
     // setting an NSOperation subclass that conforms to SDWebImageDownloaderOperationInterface - should work
-    [[SDWebImageDownloader sharedDownloader] setOperationClass:[CustomDownloaderOperation class]];
-    expect([SDWebImageDownloader sharedDownloader].operationClass).to.equal([CustomDownloaderOperation class]);
+    SDWebImageDownloader.sharedDownloader.config.operationClass = [CustomDownloaderOperation class];
+    expect(SDWebImageDownloader.sharedDownloader.config.operationClass).to.equal([CustomDownloaderOperation class]);
     
     // back to the original value
-    [[SDWebImageDownloader sharedDownloader] setOperationClass:nil];
-    expect([SDWebImageDownloader sharedDownloader].operationClass).to.equal([SDWebImageDownloaderOperation class]);
+    SDWebImageDownloader.sharedDownloader.config.operationClass = nil;
+    expect(SDWebImageDownloader.sharedDownloader.config.operationClass).to.equal([SDWebImageDownloaderOperation class]);
 }
 
 - (void)test07ThatAddProgressCallbackCompletedBlockWithNilURLCallsTheCompletionBlockWithNils {
@@ -139,8 +139,8 @@
 
 - (void)test08ThatAHTTPAuthDownloadWorks {
     XCTestExpectation *expectation = [self expectationWithDescription:@"HTTP Auth download"];
-    [SDWebImageDownloader sharedDownloader].username = @"httpwatch";
-    [SDWebImageDownloader sharedDownloader].password = @"httpwatch01";
+    SDWebImageDownloader.sharedDownloader.config.username = @"httpwatch";
+    SDWebImageDownloader.sharedDownloader.config.password = @"httpwatch01";
     NSURL *imageURL = [NSURL URLWithString:@"http://www.httpwatch.com/httpgallery/authentication/authenticatedimage/default.aspx?0.35786508303135633"];
     [[SDWebImageDownloader sharedDownloader] downloadImageWithURL:imageURL options:0 progress:nil completed:^(UIImage * _Nullable image, NSData * _Nullable data, NSError * _Nullable error, BOOL finished) {
         if (image && data && !error && finished) {
@@ -150,8 +150,8 @@
         }
     }];
     [self waitForExpectationsWithCommonTimeout];
-    [SDWebImageDownloader sharedDownloader].username = nil;
-    [SDWebImageDownloader sharedDownloader].password = nil;
+    SDWebImageDownloader.sharedDownloader.config.username = nil;
+    SDWebImageDownloader.sharedDownloader.config.password = nil;
 }
 
 - (void)test09ThatProgressiveJPEGWorks {

+ 1 - 0
WebImage/SDWebImage.h

@@ -27,6 +27,7 @@ FOUNDATION_EXPORT const unsigned char WebImageVersionString[];
 #import <SDWebImage/UIView+WebCache.h>
 #import <SDWebImage/UIImageView+WebCache.h>
 #import <SDWebImage/UIImageView+HighlightedWebCache.h>
+#import <SDWebImage/SDWebImageDownloaderConfig.h>
 #import <SDWebImage/SDWebImageDownloaderOperation.h>
 #import <SDWebImage/UIButton+WebCache.h>
 #import <SDWebImage/SDWebImagePrefetcher.h>