該文章閱讀的SDWebImage的版本為4.3.3。
這個類是下載器類,管理著影像的下載。
1.公共列舉
/**
這個位列舉定義了下載器的可選項
*/
typedef NS_OPTIONS(NSUInteger, SDWebImageDownloaderOptions) {
/**
低優先順序
*/
SDWebImageDownloaderLowPriority = 1 << 0,
/**
漸進式下載
*/
SDWebImageDownloaderProgressiveDownload = 1 << 1,
/**
預設情況下,請求阻止使用NSURLCache。設定這個選項就會使用NSURLCache
*/
SDWebImageDownloaderUseNSURLCache = 1 << 2,
/**
這個選項要與上面那個選項配合使用,如果影像是從NSURLCache讀取的,
那麼回撥block中返回的image和imageData引數就是nil
*/
SDWebImageDownloaderIgnoreCachedResponse = 1 << 3,
/**
應用進入後臺時繼續下載
*/
SDWebImageDownloaderContinueInBackground = 1 << 4,
/**
通過設定NSMutableURLRequest.HTTPShouldHandleCookies = YES獲取儲存在NSHTTPCookieStore中的cookies
*/
SDWebImageDownloaderHandleCookies = 1 << 5,
/**
允許接受不受信任的SSL證書
*/
SDWebImageDownloaderAllowInvalidSSLCertificates = 1 << 6,
/**
高優先順序
*/
SDWebImageDownloaderHighPriority = 1 << 7,
/**
縮小圖片
*/
SDWebImageDownloaderScaleDownLargeImages = 1 << 8,
};
複製程式碼
/**
這個列舉定義了下載執行順序
*/
typedef NS_ENUM(NSInteger, SDWebImageDownloaderExecutionOrder) {
/**
先進先出,預設情況
*/
SDWebImageDownloaderFIFOExecutionOrder,
/**
後進先出
*/
SDWebImageDownloaderLIFOExecutionOrder
};
複製程式碼
2.公共常量
/**
下載開始通知名稱
*/
FOUNDATION_EXPORT NSString * _Nonnull const SDWebImageDownloadStartNotification;
複製程式碼
/**
下載停止通知名稱
*/
FOUNDATION_EXPORT NSString * _Nonnull const SDWebImageDownloadStopNotification;
複製程式碼
3.公共型別定義
/**
下載進度回撥block
*/
typedef void(^SDWebImageDownloaderProgressBlock)(NSInteger receivedSize, NSInteger expectedSize, NSURL * _Nullable targetURL);
複製程式碼
/**
下載完成回撥block
*/
typedef void(^SDWebImageDownloaderCompletedBlock)(UIImage * _Nullable image, NSData * _Nullable data, NSError * _Nullable error, BOOL finished);
複製程式碼
/**
HTTP請求頭字典
*/
typedef NSDictionary<NSString *, NSString *> SDHTTPHeadersDictionary;
複製程式碼
/**
HTTP請求頭可變字典
*/
typedef NSMutableDictionary<NSString *, NSString *> SDHTTPHeadersMutableDictionary;
複製程式碼
/**
HTTP請求頭過濾演算法block
*/
typedef SDHTTPHeadersDictionary * _Nullable (^SDWebImageDownloaderHeadersFilterBlock)(NSURL * _Nullable url, SDHTTPHeadersDictionary * _Nullable headers);
複製程式碼
4.SDWebImageDownloadToken類
4.1 公共屬性
/**
用於下載的url
*/
@property (nonatomic, strong, nullable) NSURL *url;
複製程式碼
/**
用於取消的token
*/
@property (nonatomic, strong, nullable) id downloadOperationCancelToken;
複製程式碼
4.2 類擴充套件屬性
/**
下載操作物件
*/
@property (nonatomic, weak, nullable) NSOperation<SDWebImageDownloaderOperationInterface> *downloadOperation;
複製程式碼
4.3 實現
- (void)cancel {
// 有下載操作物件
if (self.downloadOperation) {
// 有取消token
SDWebImageDownloadToken *cancelToken = self.downloadOperationCancelToken;
if (cancelToken) {
// 取消下載操作
[self.downloadOperation cancel:cancelToken];
}
}
}
複製程式碼
5.公共屬性
/**
解壓影像可以提高效能,但會佔用大量記憶體。
預設為YES。如果由於過多的記憶體消耗而遇到崩潰,請將此項設定為NO。
*/
@property (assign, nonatomic) BOOL shouldDecompressImages;
複製程式碼
/**
最大併發下載數量
*/
@property (assign, nonatomic) NSInteger maxConcurrentDownloads;
複製程式碼
/**
仍需要下載的載量
*/
@property (readonly, nonatomic) NSUInteger currentDownloadCount;
複製程式碼
/**
下載請求超時的時間,預設15秒
*/
@property (assign, nonatomic) NSTimeInterval downloadTimeout;
複製程式碼
/**
會話配置物件
*/
@property (readonly, nonatomic, nonnull) NSURLSessionConfiguration *sessionConfiguration;
複製程式碼
/**
下載順序
*/
@property (assign, nonatomic) SDWebImageDownloaderExecutionOrder executionOrder;
複製程式碼
/**
請求操作的證書
*/
@property (strong, nonatomic, nullable) NSURLCredential *urlCredential;
複製程式碼
/**
證書的使用者名稱
*/
@property (strong, nonatomic, nullable) NSString *username;
複製程式碼
/**
證書的密碼
*/
@property (strong, nonatomic, nullable) NSString *password;
複製程式碼
/**
為HTTP請求頭設定過濾器
*/
@property (nonatomic, copy, nullable) SDWebImageDownloaderHeadersFilterBlock headersFilter;
複製程式碼
6.公共方法
/**
獲取單例物件
*/
+ (nonnull instancetype)sharedDownloader;
複製程式碼
/**
以指定會話配置物件初始化
*/
- (nonnull instancetype)initWithSessionConfiguration:(nullable NSURLSessionConfiguration *)sessionConfiguration NS_DESIGNATED_INITIALIZER;
複製程式碼
/**
為HTTP請求頭新增欄位
*/
- (void)setValue:(nullable NSString *)value forHTTPHeaderField:(nullable NSString *)field;
複製程式碼
/**
獲取HTTP請求頭指定欄位的值
*/
- (nullable NSString *)valueForHTTPHeaderField:(nullable NSString *)field;
複製程式碼
/**
設定下載操作物件
*/
- (void)setOperationClass:(nullable Class)operationClass;
複製程式碼
/**
下載指定url的影像
*/
- (nullable SDWebImageDownloadToken *)downloadImageWithURL:(nullable NSURL *)url
options:(SDWebImageDownloaderOptions)options
progress:(nullable SDWebImageDownloaderProgressBlock)progressBlock
completed:(nullable SDWebImageDownloaderCompletedBlock)completedBlock;
複製程式碼
/**
取消指定token的操作
*/
- (void)cancel:(nullable SDWebImageDownloadToken *)token;
複製程式碼
/**
設定下載的暫停狀態
*/
- (void)setSuspended:(BOOL)suspended;
複製程式碼
/**
取消所有的下載
*/
- (void)cancelAllDownloads;
複製程式碼
/**
以指定會話配置物件建立新的會話物件
*/
- (void)createNewSessionWithConfiguration:(nonnull NSURLSessionConfiguration *)sessionConfiguration;
複製程式碼
/**
使會話物件無效並取消任務
*/
- (void)invalidateSessionAndCancel:(BOOL)cancelPendingOperations;
複製程式碼
7.私有巨集
/**
利用GCD的訊號量實現加鎖的效果
*/
#define LOCK(lock) dispatch_semaphore_wait(lock, DISPATCH_TIME_FOREVER);
複製程式碼
/**
利用GCD的訊號量實現解鎖的效果
*/
#define UNLOCK(lock) dispatch_semaphore_signal(lock);
複製程式碼
8.類擴充套件屬性
/**
下載操作佇列
*/
@property (strong, nonatomic, nonnull) NSOperationQueue *downloadQueue;
複製程式碼
/**
最後新增的操作物件
*/
@property (weak, nonatomic, nullable) NSOperation *lastAddedOperation;
複製程式碼
/**
下載操作類
*/
@property (assign, nonatomic, nullable) Class operationClass;
複製程式碼
/**
儲存url和其對應的操作物件
*/
@property (strong, nonatomic, nonnull) NSMutableDictionary<NSURL *, SDWebImageDownloaderOperation *> *URLOperations;
複製程式碼
/**
HTTP請求頭
*/
@property (strong, nonatomic, nullable) SDHTTPHeadersMutableDictionary *HTTPHeaders;
複製程式碼
/**
用於保證對屬性URLOperations操作執行緒安全的鎖
*/
@property (strong, nonatomic, nonnull) dispatch_semaphore_t operationsLock;
複製程式碼
/**
用於保證對屬性HTTPHeaders操作執行緒安全的鎖
*/
@property (strong, nonatomic, nonnull) dispatch_semaphore_t headersLock;
複製程式碼
/**
會話物件
*/
@property (strong, nonatomic) NSURLSession *session;
複製程式碼
9.實現
9.1 生命週期方法
+ (void)initialize {
// 如果獲取到了SDNetworkActivityIndicator類
if (NSClassFromString(@"SDNetworkActivityIndicator")) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
// 獲取SDNetworkActivityIndicator類的單例物件
id activityIndicator = [NSClassFromString(@"SDNetworkActivityIndicator") performSelector:NSSelectorFromString(@"sharedActivityIndicator")];
#pragma clang diagnostic pop
// 移除之前新增的觀察者
[[NSNotificationCenter defaultCenter] removeObserver:activityIndicator name:SDWebImageDownloadStartNotification object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:activityIndicator name:SDWebImageDownloadStopNotification object:nil];
// 新增觀察者
[[NSNotificationCenter defaultCenter] addObserver:activityIndicator
selector:NSSelectorFromString(@"startActivity")
name:SDWebImageDownloadStartNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:activityIndicator
selector:NSSelectorFromString(@"stopActivity")
name:SDWebImageDownloadStopNotification object:nil];
}
}
複製程式碼
- (nonnull instancetype)init {
// 以預設會話配置物件初始化
return [self initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
}
複製程式碼
- (void)dealloc {
// 取消任務並使會話物件無效
[self.session invalidateAndCancel];
// 儲存會話物件的屬性置空
self.session = nil;
// 取消操作佇列中所有操作
[self.downloadQueue cancelAllOperations];
}
複製程式碼
9.2 私有方法
/**
新增下載操作
*/
- (nullable SDWebImageDownloadToken *)addProgressCallback:(SDWebImageDownloaderProgressBlock)progressBlock
completedBlock:(SDWebImageDownloaderCompletedBlock)completedBlock
forURL:(nullable NSURL *)url
createCallback:(SDWebImageDownloaderOperation *(^)(void))createCallback {
// url是必傳的
if (url == nil) {
if (completedBlock != nil) {
completedBlock(nil, nil, nil, NO);
}
return nil;
}
// 加鎖
LOCK(self.operationsLock);
// 從快取中獲取url對應的操作物件
SDWebImageDownloaderOperation *operation = [self.URLOperations objectForKey:url];
// 如果沒獲取到,防止同一影像重複下載
if (!operation) {
// 從引數中獲取操作物件
operation = createCallback();
__weak typeof(self) wself = self;
operation.completionBlock = ^{
// 操作完成時,從快取中移除該url對應的操作物件
__strong typeof(wself) sself = wself;
if (!sself) {
return;
}
LOCK(sself.operationsLock);
[sself.URLOperations removeObjectForKey:url];
UNLOCK(sself.operationsLock);
};
// 快取url和其對應的操作物件
[self.URLOperations setObject:operation forKey:url];
// 將操作物件新增到操作佇列中
[self.downloadQueue addOperation:operation];
}
// 解鎖
UNLOCK(self.operationsLock);
// 生成下載操作取消token
id downloadOperationCancelToken = [operation addHandlersForProgress:progressBlock completed:completedBlock];
// 生成下載token
SDWebImageDownloadToken *token = [SDWebImageDownloadToken new];
token.downloadOperation = operation;
token.url = url;
token.downloadOperationCancelToken = downloadOperationCancelToken;
// 返回token
return token;
}
複製程式碼
/**
獲取操作佇列中task對應的下載操作物件
*/
- (SDWebImageDownloaderOperation *)operationWithTask:(NSURLSessionTask *)task {
// 建立變數奧村下載操作物件
SDWebImageDownloaderOperation *returnOperation = nil;
// 遍歷找到task對應的下載操作物件
for (SDWebImageDownloaderOperation *operation in self.downloadQueue.operations) {
if (operation.dataTask.taskIdentifier == task.taskIdentifier) {
returnOperation = operation;
break;
}
}
// 返回下載操作物件
return returnOperation;
}
複製程式碼
9.3 公共方法
+ (nonnull instancetype)sharedDownloader {
// 獲取該類的單例物件
static dispatch_once_t once;
static id instance;
dispatch_once(&once, ^{
instance = [self new];
});
return instance;
}
複製程式碼
- (nonnull instancetype)initWithSessionConfiguration:(nullable NSURLSessionConfiguration *)sessionConfiguration {
if ((self = [super init])) {
// 操作物件類預設是SDWebImageDownloaderOperation
_operationClass = [SDWebImageDownloaderOperation class];
// 預設是解壓縮影像
_shouldDecompressImages = YES;
// 預設順序是先進先出
_executionOrder = SDWebImageDownloaderFIFOExecutionOrder;
// 初始化操作佇列物件
_downloadQueue = [NSOperationQueue new];
// 預設最大併發下載數為6
_downloadQueue.maxConcurrentOperationCount = 6;
// 設定操作佇列物件的名稱
_downloadQueue.name = @"com.hackemist.SDWebImageDownloader";
// 初始化字典
_URLOperations = [NSMutableDictionary new];
#ifdef SD_WEBP
// 如果有webp格式的影像的HTTP請求頭
_HTTPHeaders = [@{@"Accept": @"image/webp,image/*;q=0.8"} mutableCopy];
#else
// 如果沒有webp格式的影像的HTTP請求頭
_HTTPHeaders = [@{@"Accept": @"image/*;q=0.8"} mutableCopy];
#endif
// 利用GCD的訊號量初始化鎖
_operationsLock = dispatch_semaphore_create(1);
// 利用GCD的訊號量初始化鎖
_headersLock = dispatch_semaphore_create(1);
// 預設15秒下載請求超時
_downloadTimeout = 15.0;
// 建立會話物件
[self createNewSessionWithConfiguration:sessionConfiguration];
}
return self;
}
複製程式碼
- (void)createNewSessionWithConfiguration:(NSURLSessionConfiguration *)sessionConfiguration {
// 取消所有下載
[self cancelAllDownloads];
// 如果當前有會話就物件就取消會話物件的任務並使會話物件無效
if (self.session) {
[self.session invalidateAndCancel];
}
// 設定會話配置物件的請求超時時間
sessionConfiguration.timeoutIntervalForRequest = self.downloadTimeout;
// 建立會話物件
self.session = [NSURLSession sessionWithConfiguration:sessionConfiguration
delegate:self
delegateQueue:nil];
}
複製程式碼
- (void)invalidateSessionAndCancel:(BOOL)cancelPendingOperations {
// 當前類是SDWebImageDownloader的單例物件就不繼續向下執行
if (self == [SDWebImageDownloader sharedDownloader]) {
return;
}
if (cancelPendingOperations) {
// 取消任務並使會話物件無效
[self.session invalidateAndCancel];
} else {
// 等待任務完成並使會話物件無效
[self.session finishTasksAndInvalidate];
}
}
複製程式碼
- (void)setValue:(nullable NSString *)value forHTTPHeaderField:(nullable NSString *)field {
// 加鎖
LOCK(self.headersLock);
if (value) {
// 如果傳入了值,就給指定欄位賦值
self.HTTPHeaders[field] = value;
} else {
// 如果未傳值,就刪除指定欄位
[self.HTTPHeaders removeObjectForKey:field];
}
// 解鎖
UNLOCK(self.headersLock);
}
複製程式碼
- (nullable NSString *)valueForHTTPHeaderField:(nullable NSString *)field {
// 獲取HTTP頭中指定欄位的值
if (!field) {
return nil;
}
return [[self allHTTPHeaderFields] objectForKey:field];
}
複製程式碼
- (void)setOperationClass:(nullable Class)operationClass {
// 操作物件類必須是NSOperation類的子類,並且遵守了SDWebImageDownloaderOperationInterface協議,否則就設定為SDWebImageDownloaderOperation類
if (operationClass && [operationClass isSubclassOfClass:[NSOperation class]] && [operationClass conformsToProtocol:@protocol(SDWebImageDownloaderOperationInterface)]) {
_operationClass = operationClass;
} else {
_operationClass = [SDWebImageDownloaderOperation class];
}
}
複製程式碼
- (nullable SDWebImageDownloadToken *)downloadImageWithURL:(nullable NSURL *)url
options:(SDWebImageDownloaderOptions)options
progress:(nullable SDWebImageDownloaderProgressBlock)progressBlock
completed:(nullable SDWebImageDownloaderCompletedBlock)completedBlock {
__weak SDWebImageDownloader *wself = self;
// 新增任務相關引數
return [self addProgressCallback:progressBlock completedBlock:completedBlock forURL:url createCallback:^SDWebImageDownloaderOperation *{
__strong __typeof (wself) sself = wself;
// 獲取下載請求超時時間,預設15秒
NSTimeInterval timeoutInterval = sself.downloadTimeout;
if (timeoutInterval == 0.0) {
timeoutInterval = 15.0;
}
// 根據設定的選項不同,設定不同的請求快取策略
NSURLRequestCachePolicy cachePolicy = options & SDWebImageDownloaderUseNSURLCache ? NSURLRequestUseProtocolCachePolicy : NSURLRequestReloadIgnoringLocalCacheData;
// 建立請求物件
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url
cachePolicy:cachePolicy
timeoutInterval:timeoutInterval];
// Cookies處理方式
request.HTTPShouldHandleCookies = (options & SDWebImageDownloaderHandleCookies);
// 預設使用管線化
request.HTTPShouldUsePipelining = YES;
// 設定HTTP請求頭欄位
if (sself.headersFilter) {
request.allHTTPHeaderFields = sself.headersFilter(url, [sself allHTTPHeaderFields]);
}
else {
request.allHTTPHeaderFields = [sself allHTTPHeaderFields];
}
// 建立下載操作物件
SDWebImageDownloaderOperation *operation = [[sself.operationClass alloc] initWithRequest:request inSession:sself.session options:options];
// 設定下載操作物件是否解壓縮
operation.shouldDecompressImages = sself.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 (options & SDWebImageDownloaderHighPriority) {
operation.queuePriority = NSOperationQueuePriorityHigh;
} else if (options & SDWebImageDownloaderLowPriority) {
operation.queuePriority = NSOperationQueuePriorityLow;
}
// 如果設定了後進先出就通過新增依賴的方式實現
if (sself.executionOrder == SDWebImageDownloaderLIFOExecutionOrder) {
[sself.lastAddedOperation addDependency:operation];
sself.lastAddedOperation = operation;
}
// 將生成的操作物件作為引數傳遞
return operation;
}];
}
複製程式碼
- (void)cancel:(nullable SDWebImageDownloadToken *)token {
// 獲取token中的url,如果沒有就不繼續執行了
NSURL *url = token.url;
if (!url) {
return;
}
// 加鎖
LOCK(self.operationsLock);
// 獲取到url對應的操作物件
SDWebImageDownloaderOperation *operation = [self.URLOperations objectForKey:url];
// 取消操作
if (operation) {
BOOL canceled = [operation cancel:token.downloadOperationCancelToken];
// 移除url對應的操作物件
if (canceled) {
[self.URLOperations removeObjectForKey:url];
}
}
// 解鎖
UNLOCK(self.operationsLock);
}
複製程式碼
- (void)setSuspended:(BOOL)suspended {
// 設定暫停狀態
self.downloadQueue.suspended = suspended;
}
複製程式碼
- (void)cancelAllDownloads {
// 取消所有操作
[self.downloadQueue cancelAllOperations];
}
複製程式碼
9.4 自定義getting/setting
- (void)setMaxConcurrentDownloads:(NSInteger)maxConcurrentDownloads {
// 直接給下載操作佇列物件的最大併發數賦值
_downloadQueue.maxConcurrentOperationCount = maxConcurrentDownloads;
}
- (NSInteger)maxConcurrentDownloads {
// 返回下載操作佇列物件的最大併發數
return _downloadQueue.maxConcurrentOperationCount;
}
複製程式碼
- (NSUInteger)currentDownloadCount {
// 返回當前下載操作佇列中操作物件數量
return _downloadQueue.operationCount;
}
複製程式碼
- (NSURLSessionConfiguration *)sessionConfiguration {
// 返回會話物件配置物件
return self.session.configuration;
}
複製程式碼
9.5 NSURLSessionDataDelegate方法實現
- (void)URLSession:(NSURLSession *)session
dataTask:(NSURLSessionDataTask *)dataTask
didReceiveResponse:(NSURLResponse *)response
completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler {
// 如果呼叫這個代理方法的dataTask是SDWebImageDownloaderOperation生成的,就將代理方法實現轉交給SDWebImageDownloaderOperation類物件去實現
SDWebImageDownloaderOperation *dataOperation = [self operationWithTask:dataTask];
if ([dataOperation respondsToSelector:@selector(URLSession:dataTask:didReceiveResponse:completionHandler:)]) {
[dataOperation URLSession:session dataTask:dataTask didReceiveResponse:response completionHandler:completionHandler];
} else {
// 如果不是的話就預設響應意向為允許
if (completionHandler) {
completionHandler(NSURLSessionResponseAllow);
}
}
}
複製程式碼
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data {
// 如果呼叫這個代理方法的dataTask是SDWebImageDownloaderOperation生成的,就將代理方法實現轉交給SDWebImageDownloaderOperation類物件去實現
SDWebImageDownloaderOperation *dataOperation = [self operationWithTask:dataTask];
if ([dataOperation respondsToSelector:@selector(URLSession:dataTask:didReceiveData:)]) {
[dataOperation URLSession:session dataTask:dataTask didReceiveData:data];
}
}
複製程式碼
- (void)URLSession:(NSURLSession *)session
dataTask:(NSURLSessionDataTask *)dataTask
willCacheResponse:(NSCachedURLResponse *)proposedResponse
completionHandler:(void (^)(NSCachedURLResponse *cachedResponse))completionHandler {
// 如果呼叫這個代理方法的dataTask是SDWebImageDownloaderOperation生成的,就將代理方法實現轉交給SDWebImageDownloaderOperation類物件去實現
SDWebImageDownloaderOperation *dataOperation = [self operationWithTask:dataTask];
if ([dataOperation respondsToSelector:@selector(URLSession:dataTask:willCacheResponse:completionHandler:)]) {
[dataOperation URLSession:session dataTask:dataTask willCacheResponse:proposedResponse completionHandler:completionHandler];
} else {
if (completionHandler) {
completionHandler(proposedResponse);
}
}
}
複製程式碼
9.6 NSURLSessionTaskDelegate方法實現
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {
// 如果呼叫這個代理方法的dataTask是SDWebImageDownloaderOperation生成的,就將代理方法實現轉交給SDWebImageDownloaderOperation類物件去實現
SDWebImageDownloaderOperation *dataOperation = [self operationWithTask:task];
if ([dataOperation respondsToSelector:@selector(URLSession:task:didCompleteWithError:)]) {
[dataOperation URLSession:session task:task didCompleteWithError:error];
}
}
複製程式碼
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task willPerformHTTPRedirection:(NSHTTPURLResponse *)response newRequest:(NSURLRequest *)request completionHandler:(void (^)(NSURLRequest * _Nullable))completionHandler {
// 如果呼叫這個代理方法的dataTask是SDWebImageDownloaderOperation生成的,就將代理方法實現轉交給SDWebImageDownloaderOperation類物件去實現
SDWebImageDownloaderOperation *dataOperation = [self operationWithTask:task];
if ([dataOperation respondsToSelector:@selector(URLSession:task:willPerformHTTPRedirection:newRequest:completionHandler:)]) {
[dataOperation URLSession:session task:task willPerformHTTPRedirection:response newRequest:request completionHandler:completionHandler];
} else {
if (completionHandler) {
completionHandler(request);
}
}
}
複製程式碼
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler {
// 如果呼叫這個代理方法的dataTask是SDWebImageDownloaderOperation生成的,就將代理方法實現轉交給SDWebImageDownloaderOperation類物件去實現
SDWebImageDownloaderOperation *dataOperation = [self operationWithTask:task];
if ([dataOperation respondsToSelector:@selector(URLSession:task:didReceiveChallenge:completionHandler:)]) {
[dataOperation URLSession:session task:task didReceiveChallenge:challenge completionHandler:completionHandler];
} else {
if (completionHandler) {
completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil);
}
}
}
複製程式碼
10.總結
這個類從字面上理解是一個下載器類,實際看程式碼,發現這個類並沒有做實際的下載,而是維護著一個NSURLSession
物件和一個NSOperationQueue
物件,管理著一些SDWebImageDownloaderOperation
物件。
SDWebImageDownloader
通過傳入的引數生成一個SDWebImageDownloaderOperation
物件,並新增到操作佇列中。具體的網路下載操作則由SDWebImageDownloaderOperation
物件自己處理。
原始碼閱讀系列:SDWebImage
原始碼閱讀:SDWebImage(二)——SDWebImageCompat
原始碼閱讀:SDWebImage(三)——NSData+ImageContentType
原始碼閱讀:SDWebImage(四)——SDWebImageCoder
原始碼閱讀:SDWebImage(五)——SDWebImageFrame
原始碼閱讀:SDWebImage(六)——SDWebImageCoderHelper
原始碼閱讀:SDWebImage(七)——SDWebImageImageIOCoder
原始碼閱讀:SDWebImage(八)——SDWebImageGIFCoder
原始碼閱讀:SDWebImage(九)——SDWebImageCodersManager
原始碼閱讀:SDWebImage(十)——SDImageCacheConfig
原始碼閱讀:SDWebImage(十一)——SDImageCache
原始碼閱讀:SDWebImage(十二)——SDWebImageDownloaderOperation
原始碼閱讀:SDWebImage(十三)——SDWebImageDownloader
原始碼閱讀:SDWebImage(十四)——SDWebImageManager
原始碼閱讀:SDWebImage(十五)——SDWebImagePrefetcher
原始碼閱讀:SDWebImage(十六)——SDWebImageTransition
原始碼閱讀:SDWebImage(十七)——UIView+WebCacheOperation
原始碼閱讀:SDWebImage(十八)——UIView+WebCache
原始碼閱讀:SDWebImage(十九)——UIImage+ForceDecode/UIImage+GIF/UIImage+MultiFormat
原始碼閱讀:SDWebImage(二十)——UIButton+WebCache
原始碼閱讀:SDWebImage(二十一)——UIImageView+WebCache/UIImageView+HighlightedWebCache