Authored by 朱小军

提交图片下载失败,走下发IP直连重试功能 review 小熊

... ... @@ -68,15 +68,24 @@ extern NSString *const SDWebImageDownloadStopNotification;
typedef void(^SDWebImageDownloaderProgressBlock)(NSInteger receivedSize, NSInteger expectedSize);
typedef void(^SDWebImageDownloaderCompletedBlock)(UIImage *image, NSData *data, NSError *error, BOOL finished);
typedef void(^SDWebImageDownloaderCompletedBlock)(NSURLRequest *request,UIImage *image, NSData *data, NSError *error, BOOL finished);
typedef NSDictionary *(^SDWebImageDownloaderHeadersFilterBlock)(NSURL *url, NSDictionary *headers);
@protocol SDWebImageDownloaderDelegate <NSObject>
@optional
/**
* 走图片下载直连ip请求时设置超时时间为5s.
*/
- (NSTimeInterval)setDirectIpRetryTimeout:(NSString *)host;
@end
/**
* Asynchronous downloader dedicated and optimized for image loading.
*/
@interface SDWebImageDownloader : NSObject
@property (weak, nonatomic) id <SDWebImageDownloaderDelegate> delegate;
/**
* Decompressing images that are downloaded and cached can improve peformance but can consume lot of memory.
* Defaults to YES. Set this to NO if you are experiencing a crash due to excessive memory consumption.
... ...
... ... @@ -118,6 +118,11 @@ static NSString *const kCompletedCallbackKey = @"completed";
[self addProgressCallback:progressBlock andCompletedBlock:completedBlock forURL:url createCallback:^{
NSTimeInterval timeoutInterval = wself.downloadTimeout;
if ([self.delegate respondsToSelector:@selector(setDirectIpRetryTimeout:)]) {
timeoutInterval = [self.delegate setDirectIpRetryTimeout:url.host];
}
if (timeoutInterval == 0.0) {
timeoutInterval = 15.0;
}
... ... @@ -146,9 +151,10 @@ static NSString *const kCompletedCallbackKey = @"completed";
if (callback) callback(receivedSize, expectedSize);
}
}
completed:^(UIImage *image, NSData *data, NSError *error, BOOL finished) {
completed:^(NSURLRequest *requestx,UIImage *image, NSData *data, NSError *error, BOOL finished) {
SDWebImageDownloader *sself = wself;
if (!sself) return;
__block NSArray *callbacksForURL;
dispatch_barrier_sync(sself.barrierQueue, ^{
callbacksForURL = [sself.URLCallbacks[url] copy];
... ... @@ -158,12 +164,13 @@ static NSString *const kCompletedCallbackKey = @"completed";
});
for (NSDictionary *callbacks in callbacksForURL) {
SDWebImageDownloaderCompletedBlock callback = callbacks[kCompletedCallbackKey];
if (callback) callback(image, data, error, finished);
if (callback) callback(requestx, image, data, error, finished);
}
}
cancelled:^{
SDWebImageDownloader *sself = wself;
if (!sself) return;
dispatch_barrier_async(sself.barrierQueue, ^{
[sself.URLCallbacks removeObjectForKey:url];
});
... ... @@ -195,7 +202,7 @@ static NSString *const kCompletedCallbackKey = @"completed";
// The URL will be used as the key to the callbacks dictionary so it cannot be nil. If it is nil immediately call the completed block with no image or data.
if (url == nil) {
if (completedBlock != nil) {
completedBlock(nil, nil, nil, NO);
completedBlock(nil,nil, nil, nil, NO);
}
return;
}
... ...
... ... @@ -125,7 +125,7 @@ NSString *const SDWebImageDownloadFinishNotification = @"SDWebImageDownloadFinis
}
else {
if (self.completedBlock) {
self.completedBlock(nil, nil, [NSError errorWithDomain:NSURLErrorDomain code:0 userInfo:@{NSLocalizedDescriptionKey : @"Connection can't be initialized"}], YES);
self.completedBlock(nil, nil, nil, [NSError errorWithDomain:NSURLErrorDomain code:0 userInfo:@{NSLocalizedDescriptionKey : @"Connection can't be initialized"}], YES);
}
}
... ... @@ -264,7 +264,7 @@ NSString *const SDWebImageDownloadFinishNotification = @"SDWebImageDownloadFinis
});
if (self.completedBlock) {
self.completedBlock(nil, nil, [NSError errorWithDomain:NSURLErrorDomain code:[((NSHTTPURLResponse *)response) statusCode] userInfo:nil], YES);
self.completedBlock(nil, nil, nil, [NSError errorWithDomain:NSURLErrorDomain code:[((NSHTTPURLResponse *)response) statusCode] userInfo:nil], YES);
}
CFRunLoopStop(CFRunLoopGetCurrent());
[self done];
... ... @@ -342,7 +342,7 @@ NSString *const SDWebImageDownloadFinishNotification = @"SDWebImageDownloadFinis
CGImageRelease(partialImageRef);
dispatch_main_sync_safe(^{
if (self.completedBlock) {
self.completedBlock(image, nil, nil, NO);
self.completedBlock(nil, image, nil, nil, NO);
}
});
}
... ... @@ -401,7 +401,7 @@ NSString *const SDWebImageDownloadFinishNotification = @"SDWebImageDownloadFinis
if (completionBlock) {
if (self.options & SDWebImageDownloaderIgnoreCachedResponse && responseFromCached) {
completionBlock(nil, nil, nil, YES);
completionBlock(nil, nil, nil, nil, YES);
} else if (self.imageData) {
UIImage *image = [UIImage sd_imageWithData:self.imageData];
NSString *key = [[SDWebImageManager sharedManager] cacheKeyForURL:self.request.URL];
... ... @@ -414,13 +414,13 @@ NSString *const SDWebImageDownloadFinishNotification = @"SDWebImageDownloadFinis
}
}
if (CGSizeEqualToSize(image.size, CGSizeZero)) {
completionBlock(nil, nil, [NSError errorWithDomain:SDWebImageErrorDomain code:0 userInfo:@{NSLocalizedDescriptionKey : @"Downloaded image has 0 pixels"}], YES);
completionBlock(nil, nil, nil, [NSError errorWithDomain:SDWebImageErrorDomain code:0 userInfo:@{NSLocalizedDescriptionKey : @"Downloaded image has 0 pixels"}], YES);
}
else {
completionBlock(image, self.imageData, nil, YES);
completionBlock(self.request, image, self.imageData, nil, YES);
}
} else {
completionBlock(nil, nil, [NSError errorWithDomain:SDWebImageErrorDomain code:0 userInfo:@{NSLocalizedDescriptionKey : @"Image data is nil"}], YES);
completionBlock(nil, nil, nil, [NSError errorWithDomain:SDWebImageErrorDomain code:0 userInfo:@{NSLocalizedDescriptionKey : @"Image data is nil"}], YES);
}
}
self.completionBlock = nil;
... ... @@ -439,7 +439,7 @@ NSString *const SDWebImageDownloadFinishNotification = @"SDWebImageDownloadFinis
}
if (self.completedBlock) {
self.completedBlock(nil, nil, error, YES);
self.completedBlock(nil, nil, nil, error, YES);
}
self.completionBlock = nil;
[self done];
... ...
... ... @@ -113,8 +113,31 @@ typedef NSString *(^SDWebImageCacheKeyFilterBlock)(NSURL *url);
* @return Return NO to prevent the downloading of the image on cache misses. If not implemented, YES is implied.
*/
- (BOOL)imageManager:(SDWebImageManager *)imageManager shouldDownloadImageForURL:(NSURL *)imageURL;
/**
* If download image from original url failed,app use img_ip retry again
*
* @param imageManager The current `SDWebImageManager`
* @param imageURL The url of the image to be downloaded
* @param options SDWebImageOptions
* @param progressBlock progressBlock
* @param completedBlock completedBlock
* @return NONE.
*/
- (void)imageManager:(SDWebImageManager *)imageManager didFailedDownloadImageWithURL:(NSURL *)imageURL
options:(SDWebImageOptions)options
progress:(SDWebImageDownloaderProgressBlock)progressBlock
completed:(SDWebImageCompletionWithFinishedBlock)completedBlock;
/**
* Controls which image should be downloaded when the image is not found in the cache.
*
* @param imageManager The current `SDWebImageManager`
* @param imageURL The url of the image to be downloaded
*
* @return Return original url
*/
- (NSString *)imageManager:(SDWebImageManager *)imageManager didSuccessedWithRequest:(NSURLRequest *)request cacheKey:(NSString *)key;
/**
* Allows to transform the image immediately after it has been downloaded and just before to cache it on disk and memory.
* NOTE: This method is called from a global queue in order to not to block the main thread.
*
... ...
... ... @@ -8,6 +8,7 @@
#import "SDWebImageManager.h"
#import <objc/message.h>
#import "SDWebImageDownloaderOperation.h"
@interface SDWebImageCombinedOperation : NSObject <SDWebImageOperation>
... ... @@ -144,7 +145,7 @@
@synchronized (self.runningOperations) {
[self.runningOperations addObject:operation];
}
NSString *key = [self cacheKeyForURL:url];
__block NSString *key = [self cacheKeyForURL:url];
operation.cacheOperation = [self.imageCache queryDiskCacheForKey:key done:^(UIImage *image, SDImageCacheType cacheType) {
if (operation.isCancelled) {
... ... @@ -179,7 +180,8 @@
// ignore image read from NSURLCache if image if cached but force refreshing
downloaderOptions |= SDWebImageDownloaderIgnoreCachedResponse;
}
id <SDWebImageOperation> subOperation = [self.imageDownloader downloadImageWithURL:url options:downloaderOptions progress:progressBlock completed:^(UIImage *downloadedImage, NSData *data, NSError *error, BOOL finished) {
id <SDWebImageOperation> subOperation = [self.imageDownloader downloadImageWithURL:url options:downloaderOptions progress:progressBlock completed:^(NSURLRequest *request,UIImage *downloadedImage, NSData *data, NSError *error, BOOL finished) {
if (weakOperation.isCancelled) {
// Do nothing if the operation was cancelled
// See #699 for more details
... ... @@ -188,19 +190,32 @@
else if (error) {
dispatch_main_sync_safe(^{
if (!weakOperation.isCancelled) {
completedBlock(nil, error, SDImageCacheTypeNone, finished, url);
completedBlock( nil, error, SDImageCacheTypeNone, finished, url);
}
});
BOOL shouldBeFailedURLAlliOSVersion = (error.code != NSURLErrorNotConnectedToInternet && error.code != NSURLErrorCancelled && error.code != NSURLErrorTimedOut);
BOOL shouldBeFailedURLiOS7 = (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1 && error.code != NSURLErrorInternationalRoamingOff && error.code != NSURLErrorCallIsActive && error.code != NSURLErrorDataNotAllowed);
if (shouldBeFailedURLAlliOSVersion || shouldBeFailedURLiOS7) {
if ([self.delegate respondsToSelector:@selector(imageManager:didFailedDownloadImageWithURL:options:progress:completed:)]) {
[self.delegate imageManager:self didFailedDownloadImageWithURL:url options:options progress:progressBlock completed:completedBlock];
}
@synchronized (self.failedURLs) {
[self.failedURLs addObject:url];
}
}
}
else {
if ([self.delegate respondsToSelector:@selector(imageManager:didSuccessedWithRequest:cacheKey:)]){
NSString * originalUrl = [self.delegate imageManager:self didSuccessedWithRequest:request cacheKey:key];
if (originalUrl.length > 0) {
key = originalUrl;
}
}
if ((options & SDWebImageRetryFailed)) {
@synchronized (self.failedURLs) {
[self.failedURLs removeObject:url];
... ...