2.7版本2012年9月8日發(fā)布
主要圍繞漸進(jìn)下載模塊支持
1. UIButton+WebCache
- 新增BackgroundImage支持
//-------------------------2.7版本更新-block支持------------------------
//設(shè)置不同狀態(tài)的按鈕背景圖片->按鈕擴(kuò)大和縮小
- (void)setBackgroundImageWithURL:(NSURL *)url;
- (void)setBackgroundImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder;
- (void)setBackgroundImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options;
#if NS_BLOCKS_AVAILABLE
- (void)setBackgroundImageWithURL:(NSURL *)url success:(SDWebImageSuccessBlock)success failure:(SDWebImageFailureBlock)failure;
- (void)setBackgroundImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder success:(SDWebImageSuccessBlock)success failure:(SDWebImageFailureBlock)failure;
- (void)setBackgroundImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options success:(SDWebImageSuccessBlock)success failure:(SDWebImageFailureBlock)failure;
#endif
//---------------------------------end--------------------------------
//--------------------2.7版本更新-BackgroundImage支持-------------------
- (void)setBackgroundImageWithURL:(NSURL *)url{
[self setBackgroundImageWithURL:url placeholderImage:nil];
}
- (void)setBackgroundImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder{
[self setBackgroundImageWithURL:url placeholderImage:placeholder options:0];
}
- (void)setBackgroundImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options{
SDWebImageManager *manager = [SDWebImageManager sharedManager];
[manager cancelForDelegate:self];
[self setBackgroundImage:placeholder forState:UIControlStateNormal];
[self setBackgroundImage:placeholder forState:UIControlStateSelected];
[self setBackgroundImage:placeholder forState:UIControlStateHighlighted];
if (url){
NSDictionary *info = [NSDictionary dictionaryWithObject:@"background" forKey:@"type"];
[manager downloadWithURL:url delegate:self options:options userInfo:info];
}
}
#if NS_BLOCKS_AVAILABLE
- (void)setBackgroundImageWithURL:(NSURL *)url success:(SDWebImageSuccessBlock)success failure:(SDWebImageFailureBlock)failure{
[self setBackgroundImageWithURL:url placeholderImage:nil success:success failure:failure];
}
- (void)setBackgroundImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder success:(SDWebImageSuccessBlock)success failure:(SDWebImageFailureBlock)failure;{
[self setBackgroundImageWithURL:url placeholderImage:placeholder options:0 success:success failure:failure];
}
- (void)setBackgroundImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options success:(SDWebImageSuccessBlock)success failure:(SDWebImageFailureBlock)failure{
SDWebImageManager *manager = [SDWebImageManager sharedManager];
// Remove in progress downloader from queue
[manager cancelForDelegate:self];
[self setBackgroundImage:placeholder forState:UIControlStateNormal];
[self setBackgroundImage:placeholder forState:UIControlStateSelected];
[self setBackgroundImage:placeholder forState:UIControlStateHighlighted];
if (url){
NSDictionary *info = [NSDictionary dictionaryWithObject:@"background" forKey:@"type"];
[manager downloadWithURL:url delegate:self options:options userInfo:info success:success failure:failure];
}
}
#endif
//---------------------------------end--------------------------------
//----------------------------2.7版本更新-優(yōu)化---------------------------
- (void)webImageManager:(SDWebImageManager *)imageManager didProgressWithPartialImage:(UIImage *)image forURL:(NSURL *)url userInfo:(NSDictionary *)info{
if ([[info valueForKey:@"type"] isEqualToString:@"background"]){
[self setBackgroundImage:image forState:UIControlStateNormal];
[self setBackgroundImage:image forState:UIControlStateSelected];
[self setBackgroundImage:image forState:UIControlStateHighlighted];
} else {
[self setImage:image forState:UIControlStateNormal];
[self setImage:image forState:UIControlStateSelected];
[self setImage:image forState:UIControlStateHighlighted];
}
}
- (void)webImageManager:(SDWebImageManager *)imageManager didFinishWithImage:(UIImage *)image forURL:(NSURL *)url userInfo:(NSDictionary *)info{
if ([[info valueForKey:@"type"] isEqualToString:@"background"]){
[self setBackgroundImage:image forState:UIControlStateNormal];
[self setBackgroundImage:image forState:UIControlStateSelected];
[self setBackgroundImage:image forState:UIControlStateHighlighted];
} else {
[self setImage:image forState:UIControlStateNormal];
[self setImage:image forState:UIControlStateSelected];
[self setImage:image forState:UIControlStateHighlighted];
}
}
//---------------------------------end--------------------------------
2. SDWebImageManager
- 新增SDWebImageOptions圖片模式漸進(jìn)下載
typedef enum{
//如果下載失敗行楞,還會(huì)繼續(xù)嘗試下載
SDWebImageRetryFailed = 1 << 0,
//滑動(dòng)的時(shí)候Scrollview不下載闷游,手從屏幕上移走荷并,Scrollview開始減速的時(shí)候才會(huì)開始下載圖片
SDWebImageLowPriority = 1 << 1,
//禁止磁盤緩存,只有內(nèi)存緩存
SDWebImageCacheMemoryOnly = 1 << 2,
//------------------2.7版本更新-漸進(jìn)下載----------------------
//正常情況圖片下載完成遏插,然后一次性顯示,設(shè)置該選項(xiàng)那么圖片邊下載邊顯示
SDWebImageProgressiveDownload = 1 << 3
//--------------------------end----------------------------
} SDWebImageOptions;
- 增加了block回調(diào)支持
//------------------2.7版本更新-增加block支持----------------------
#if NS_BLOCKS_AVAILABLE
typedef void(^SDWebImageSuccessBlock)(UIImage *image, BOOL cached);
typedef void(^SDWebImageFailureBlock)(NSError *error);
#endif
//--------------------------end-----------------------------
- 新增URL緩存過(guò)濾器block
//------------------2.7版本更新-過(guò)濾URL----------------------
//[[SDWebImageManager sharedManager] setCacheKeyFilter:^(NSURL *url){
// url = [[NSURL alloc] initWithScheme:url.scheme host:url.host path:url.path];
// return [url absoluteString];
//}];
#if NS_BLOCKS_AVAILABLE
typedef NSString *(^CacheKeyFilter)(NSURL *url);
@property (strong) CacheKeyFilter cacheKeyFilter;
#endif
//--------------------------end----------------------------
- 廢棄了一個(gè)方法
//------------------2.7版本更新-廢棄----------------------
- (UIImage *)imageWithURL:(NSURL *)url __attribute__ ((deprecated));
//--------------------------end----------------------------
- 新增一個(gè)下載重載方法
//------------------2.7版本更新-方法重載----------------------
//如果不在緩存中驹暑,則在給定URL處下載圖像移袍,否則返回緩存版本
- (void)downloadWithURL:(NSURL *)url delegate:(id<SDWebImageManagerDelegate>)delegate options:(SDWebImageOptions)options userInfo:(NSDictionary *)info;
//--------------------------end-----------------------------
- 新增下載緩存信息集合
@interface SDWebImageManager : NSObject <SDWebImageDownloaderDelegate, SDImageCacheDelegate>{
NSMutableArray *downloaders;
NSMutableDictionary *downloaderForURL;
NSMutableArray *failedURLs;
NSMutableArray *downloadDelegates;
NSMutableArray *cacheDelegates;
NSMutableArray *cacheURLs;
//------------------2.7版本更新-緩存信息----------------------
NSMutableArray *downloadInfo;
//--------------------------end----------------------------
}
+ (id)sharedManager;
//------------------2.7版本更新-兼容block----------------------
#if NS_BLOCKS_AVAILABLE
@synthesize cacheKeyFilter;
#endif
//--------------------------end------------------------------
//-----------------------2.7版本更新-優(yōu)化-----------------------
- (void)downloadWithURL:(NSURL *)url delegate:(id<SDWebImageManagerDelegate>)delegate options:(SDWebImageOptions)options userInfo:(NSDictionary *)userInfo{
//非常常見(jiàn)的錯(cuò)誤是使用NSString對(duì)象而不是NSURL發(fā)送URL。出于某種奇怪的原因孝治,
//XCode不會(huì)為這種類型不匹配拋出任何警告列粪。在這里审磁,我們通過(guò)允許url作為NSString傳遞來(lái)防止這個(gè)錯(cuò)誤。
if ([url isKindOfClass:NSString.class]){
url = [NSURL URLWithString:(NSString *)url];
} else if (![url isKindOfClass:NSURL.class]){
//防止由于NSNull等常見(jiàn)錯(cuò)誤值而導(dǎo)致的一些常見(jiàn)崩潰岂座。例如零
url = nil;
}
if (!url || !delegate || (!(options & SDWebImageRetryFailed) && [failedURLs containsObject:url])){
return;
}
//檢查磁盤上的緩存異步态蒂,這樣我們就不會(huì)阻塞主線程
[cacheDelegates addObject:delegate];
[cacheURLs addObject:url];
NSDictionary *info = [NSDictionary dictionaryWithObjectsAndKeys:
delegate,
@"delegate",
url,
@"url",
[NSNumber numberWithInt:options],
@"options",
userInfo ? userInfo : [NSNull null],
@"userInfo",
nil];
[[SDImageCache sharedImageCache] queryDiskCacheForKey:[self cacheKeyForURL:url] delegate:self userInfo:info];
}
//-----------------------------end----------------------------
//-----------------------2.7版本更新-支持block-----------------------
- (void)downloadWithURL:(NSURL *)url delegate:(id)delegate options:(SDWebImageOptions)options userInfo:(NSDictionary *)userInfo success:(SDWebImageSuccessBlock)success failure:(SDWebImageFailureBlock)failure{
//由于iOS版本需要向后壓縮而沒(méi)有塊
//所以從上面重復(fù)的邏輯非常常見(jiàn)的錯(cuò)誤是使用NSString對(duì)象而不是NSURL發(fā)送URL。出于某種奇怪的原因费什,
//XCode不會(huì)為這種類型不匹配拋出任何警告钾恢。在這里,我們通過(guò)允許url作為NSString傳遞來(lái)防止這個(gè)錯(cuò)誤鸳址。
if ([url isKindOfClass:NSString.class]){
url = [NSURL URLWithString:(NSString *)url];
}
if (!url || !delegate || (!(options & SDWebImageRetryFailed) && [failedURLs containsObject:url])){
return;
}
//檢查磁盤上的緩存異步瘩蚪,這樣我們就不會(huì)阻塞主線程
[cacheDelegates addObject:delegate];
[cacheURLs addObject:url];
SDWebImageSuccessBlock successCopy = [success copy];
SDWebImageFailureBlock failureCopy = [failure copy];
NSDictionary *info = [NSDictionary dictionaryWithObjectsAndKeys:
delegate, @"delegate",
url, @"url",
[NSNumber numberWithInt:options], @"options",
userInfo ? userInfo : [NSNull null], @"userInfo",
successCopy, @"success",
failureCopy, @"failure",
nil];
SDWIRelease(successCopy);
SDWIRelease(failureCopy);
[[SDImageCache sharedImageCache] queryDiskCacheForKey:[self cacheKeyForURL:url] delegate:self userInfo:info];
}
#endif
//--------------------------------end------------------------------
- (void)cancelForDelegate:(id<SDWebImageManagerDelegate>)delegate{
NSUInteger idx;
while ((idx = [cacheDelegates indexOfObjectIdenticalTo:delegate]) != NSNotFound){
[cacheDelegates removeObjectAtIndex:idx];
[cacheURLs removeObjectAtIndex:idx];
}
while ((idx = [downloadDelegates indexOfObjectIdenticalTo:delegate]) != NSNotFound){
SDWebImageDownloader *downloader = SDWIReturnRetained([downloaders objectAtIndex:idx]);
//----------------------2.7版本更新-功能更新---------------------
[downloadInfo removeObjectAtIndex:idx];
//----------------------------end-----------------------------
[downloadDelegates removeObjectAtIndex:idx];
[downloaders removeObjectAtIndex:idx];
if (![downloaders containsObject:downloader]){
//沒(méi)有更多的委托在等待這個(gè)下載,取消它
[downloader cancel];
[downloaderForURL removeObjectForKey:downloader.url];
}
SDWIRelease(downloader);
}
}
- (void)imageCache:(SDImageCache *)imageCache didFindImage:(UIImage *)image forKey:(NSString *)key userInfo:(NSDictionary *)info{
NSURL *url = [info objectForKey:@"url"];
id<SDWebImageManagerDelegate> delegate = [info objectForKey:@"delegate"];
NSUInteger idx = [self indexOfDelegate:delegate waitingForURL:url];
if (idx == NSNotFound){
//請(qǐng)求已被取消
return;
}
if ([delegate respondsToSelector:@selector(webImageManager:didFinishWithImage:)]){
[delegate performSelector:@selector(webImageManager:didFinishWithImage:) withObject:self withObject:image];
}
if ([delegate respondsToSelector:@selector(webImageManager:didFinishWithImage:forURL:)]){
objc_msgSend(delegate, @selector(webImageManager:didFinishWithImage:forURL:), self, image, url);
}
//--------------------------2.7版本更新-優(yōu)化--------------------------
if ([delegate respondsToSelector:@selector(webImageManager:didFinishWithImage:forURL:userInfo:)]){
NSDictionary *userInfo = [info objectForKey:@"userInfo"];
if ([userInfo isKindOfClass:NSNull.class]){
userInfo = nil;
}
objc_msgSend(delegate, @selector(webImageManager:didFinishWithImage:forURL:userInfo:), self, image, url, userInfo);
}
//--------------------------------end-------------------------------
#if NS_BLOCKS_AVAILABLE
if ([info objectForKey:@"success"]){
SDWebImageSuccessBlock success = [info objectForKey:@"success"];
success(image, YES);
}
#endif
[cacheDelegates removeObjectAtIndex:idx];
[cacheURLs removeObjectAtIndex:idx];
}
- (void)imageCache:(SDImageCache *)imageCache didNotFindImageForKey:(NSString *)key userInfo:(NSDictionary *)info{
NSURL *url = [info objectForKey:@"url"];
id<SDWebImageManagerDelegate> delegate = [info objectForKey:@"delegate"];
SDWebImageOptions options = [[info objectForKey:@"options"] intValue];
NSUInteger idx = [self indexOfDelegate:delegate waitingForURL:url];
if (idx == NSNotFound){
//請(qǐng)求已被取消
return;
}
[cacheDelegates removeObjectAtIndex:idx];
[cacheURLs removeObjectAtIndex:idx];
//為相同的URL共享相同的下載加載程序稿黍,所以我們不會(huì)多次下載相同的URL
SDWebImageDownloader *downloader = [downloaderForURL objectForKey:url];
if (!downloader){
downloader = [SDWebImageDownloader downloaderWithURL:url delegate:self userInfo:info lowPriority:(options & SDWebImageLowPriority)];
[downloaderForURL setObject:downloader forKey:url];
} else {
//重用共享下載器
downloader.lowPriority = (options & SDWebImageLowPriority);
}
//------------------------2.7版本更新-優(yōu)化----------------------
if ((options & SDWebImageProgressiveDownload) && !downloader.progressive){
//根據(jù)需要提供漸進(jìn)式下載支持
downloader.progressive = YES;
}
//----------------------------end-----------------------------
[downloadInfo addObject:info];
[downloadDelegates addObject:delegate];
[downloaders addObject:downloader];
}
- (void)imageDownloader:(SDWebImageDownloader *)downloader didFinishWithImage:(UIImage *)image{
SDWIRetain(downloader);
SDWebImageOptions options = [[downloader.userInfo objectForKey:@"options"] intValue];
//用這個(gè)下載器通知所有下載delegate
for (NSInteger idx = (NSInteger)[downloaders count] - 1; idx >= 0; idx--){
NSUInteger uidx = (NSUInteger)idx;
SDWebImageDownloader *aDownloader = [downloaders objectAtIndex:uidx];
if (aDownloader == downloader){
id<SDWebImageManagerDelegate> delegate = [downloadDelegates objectAtIndex:uidx];
SDWIRetain(delegate);
SDWIAutorelease(delegate);
if (image){
if ([delegate respondsToSelector:@selector(webImageManager:didFinishWithImage:)]){
[delegate performSelector:@selector(webImageManager:didFinishWithImage:) withObject:self withObject:image];
}
if ([delegate respondsToSelector:@selector(webImageManager:didFinishWithImage:forURL:)]){
objc_msgSend(delegate, @selector(webImageManager:didFinishWithImage:forURL:), self, image, downloader.url);
}
//-------------------2.7版本更新-優(yōu)化-新增方法重載-------------------
if ([delegate respondsToSelector:@selector(webImageManager:didFinishWithImage:forURL:userInfo:)]){
NSDictionary *userInfo = [[downloadInfo objectAtIndex:uidx] objectForKey:@"userInfo"];
if ([userInfo isKindOfClass:NSNull.class]){
userInfo = nil;
}
objc_msgSend(delegate, @selector(webImageManager:didFinishWithImage:forURL:userInfo:), self, image, downloader.url, userInfo);
}
//--------------------------------end---------------------------
//--------------2.7版本更新-block支持優(yōu)化----------------
#if NS_BLOCKS_AVAILABLE
if ([[downloadInfo objectAtIndex:uidx] objectForKey:@"success"]){
SDWebImageSuccessBlock success = [[downloadInfo objectAtIndex:uidx] objectForKey:@"success"];
success(image, NO);
}
#endif
//-------------------------end------------------------
} else {
if ([delegate respondsToSelector:@selector(webImageManager:didFailWithError:)]){
[delegate performSelector:@selector(webImageManager:didFailWithError:) withObject:self withObject:nil];
}
if ([delegate respondsToSelector:@selector(webImageManager:didFailWithError:forURL:)]){
objc_msgSend(delegate, @selector(webImageManager:didFailWithError:forURL:), self, nil, downloader.url);
}
//-------------------2.7版本更新-優(yōu)化-新增方法重載-------------------
if ([delegate respondsToSelector:@selector(webImageManager:didFailWithError:forURL:userInfo:)]){
NSDictionary *userInfo = [[downloadInfo objectAtIndex:uidx] objectForKey:@"userInfo"];
if ([userInfo isKindOfClass:NSNull.class]){
userInfo = nil;
}
objc_msgSend(delegate, @selector(webImageManager:didFailWithError:forURL:userInfo:), self, nil, downloader.url, userInfo);
}
//--------------------------------end---------------------------
#if NS_BLOCKS_AVAILABLE
if ([[downloadInfo objectAtIndex:uidx] objectForKey:@"failure"]){
SDWebImageFailureBlock failure = [[downloadInfo objectAtIndex:uidx] objectForKey:@"failure"];
failure(nil);
}
#endif
}
[downloaders removeObjectAtIndex:uidx];
[downloadInfo removeObjectAtIndex:uidx];
[downloadDelegates removeObjectAtIndex:uidx];
}
}
if (image){
//將圖像存儲(chǔ)在緩存中
[[SDImageCache sharedImageCache] storeImage:image
imageData:downloader.imageData
forKey:[self cacheKeyForURL:downloader.url]
toDisk:!(options & SDWebImageCacheMemoryOnly)];
} else if (!(options & SDWebImageRetryFailed)){
// 無(wú)法從這個(gè)URL下載圖像疹瘦,將URL標(biāo)記為failed,這樣我們就不會(huì)一次又一次地嘗試失敗
//(只有在SDWebImageRetryFailed未被激活時(shí)才這樣做)
[failedURLs addObject:downloader.url];
}
//釋放下載器
[downloaderForURL removeObjectForKey:downloader.url];
SDWIRelease(downloader);
}
- (void)imageDownloader:(SDWebImageDownloader *)downloader didFailWithError:(NSError *)error{
SDWIRetain(downloader);
//用這個(gè)下載器通知所有下載delegate
for (NSInteger idx = (NSInteger)[downloaders count] - 1; idx >= 0; idx--){
NSUInteger uidx = (NSUInteger)idx;
SDWebImageDownloader *aDownloader = [downloaders objectAtIndex:uidx];
if (aDownloader == downloader){
id<SDWebImageManagerDelegate> delegate = [downloadDelegates objectAtIndex:uidx];
SDWIRetain(delegate);
SDWIAutorelease(delegate);
if ([delegate respondsToSelector:@selector(webImageManager:didFailWithError:)]){
[delegate performSelector:@selector(webImageManager:didFailWithError:) withObject:self withObject:error];
}
if ([delegate respondsToSelector:@selector(webImageManager:didFailWithError:forURL:)]){
objc_msgSend(delegate, @selector(webImageManager:didFailWithError:forURL:), self, error, downloader.url);
}
//-------------------2.7版本更新-優(yōu)化-新增方法重載-------------------
if ([delegate respondsToSelector:@selector(webImageManager:didFailWithError:forURL:userInfo:)]){
NSDictionary *userInfo = [[downloadInfo objectAtIndex:uidx] objectForKey:@"userInfo"];
if ([userInfo isKindOfClass:NSNull.class])
{
userInfo = nil;
}
objc_msgSend(delegate, @selector(webImageManager:didFailWithError:forURL:userInfo:), self, error, downloader.url, userInfo);
}
//--------------------------------end---------------------------
//--------------2.7版本更新-block支持優(yōu)化----------------
#if NS_BLOCKS_AVAILABLE
if ([[downloadInfo objectAtIndex:uidx] objectForKey:@"failure"]){
SDWebImageFailureBlock failure = [[downloadInfo objectAtIndex:uidx] objectForKey:@"failure"];
failure(error);
}
#endif
//-------------------------end------------------------
[downloaders removeObjectAtIndex:uidx];
[downloadInfo removeObjectAtIndex:uidx];
[downloadDelegates removeObjectAtIndex:uidx];
}
}
[downloaderForURL removeObjectForKey:downloader.url];
SDWIRelease(downloader);
}
//--------------------------2.7版本更新-新增功能----------------------------
- (void)imageDownloader:(SDWebImageDownloader *)downloader didUpdatePartialImage:(UIImage *)image{
//用這個(gè)下載器通知所有下載delegate
for (NSInteger idx = (NSInteger)[downloaders count] - 1; idx >= 0; idx--){
NSUInteger uidx = (NSUInteger)idx;
SDWebImageDownloader *aDownloader = [downloaders objectAtIndex:uidx];
if (aDownloader == downloader){
id<SDWebImageManagerDelegate> delegate = [downloadDelegates objectAtIndex:uidx];
SDWIRetain(delegate);
SDWIAutorelease(delegate);
if ([delegate respondsToSelector:@selector(webImageManager:didProgressWithPartialImage:forURL:)]){
objc_msgSend(delegate, @selector(webImageManager:didProgressWithPartialImage:forURL:), self, image, downloader.url);
}
if ([delegate respondsToSelector:@selector(webImageManager:didProgressWithPartialImage:forURL:userInfo:)]){
NSDictionary *userInfo = [[downloadInfo objectAtIndex:uidx] objectForKey:@"userInfo"];
if ([userInfo isKindOfClass:NSNull.class]){
userInfo = nil;
}
objc_msgSend(delegate, @selector(webImageManager:didProgressWithPartialImage:forURL:userInfo:), self, image, downloader.url, userInfo);
}
}
}
}
//----------------------------------end------------------------------------
3. SDWebImageDownloader
- 新增三個(gè)屬性
@interface SDWebImageDownloader : NSObject{
@private
NSURL *url;
SDWIWeak id<SDWebImageDownloaderDelegate> delegate;
NSURLConnection *connection;
NSMutableData *imageData;
id userInfo;
BOOL lowPriority;
//-----------------------2.7版本更新-功能優(yōu)化-----------------------
NSUInteger expectedSize;
BOOL progressive;
size_t width, height;
//-----------------------------end-------------------------------
}
//-----------------------2.7版本更新-功能優(yōu)化--------------
//如果設(shè)置為YES巡球,則啟用漸進(jìn)式下載支持
//正常情況圖片下載完成言沐,然后一次性顯示
//設(shè)置為YES之后邓嘹,圖片邊下載邊顯示
@property (nonatomic, readwrite) BOOL progressive;
//-----------------------------end----------------------
- 支持漸進(jìn)下載傳遞NSData-網(wǎng)絡(luò)請(qǐng)求回調(diào)中優(yōu)化
- (void)connection:(NSURLConnection *)aConnection didReceiveResponse:(NSURLResponse *)response{
//-----------------------------2.7版本更新-功能優(yōu)化-------------------------
if (![response respondsToSelector:@selector(statusCode)] || [((NSHTTPURLResponse *)response) statusCode] < 400){
expectedSize = response.expectedContentLength > 0 ? (NSUInteger)response.expectedContentLength : 0;
self.imageData = SDWIReturnAutoreleased([[NSMutableData alloc] initWithCapacity:expectedSize]);
//----------------------------------end----------------------------------
} else {
[aConnection cancel];
[[NSNotificationCenter defaultCenter] postNotificationName:SDWebImageDownloadStopNotification object:nil];
if ([delegate respondsToSelector:@selector(imageDownloader:didFailWithError:)]){
NSError *error = [[NSError alloc] initWithDomain:NSURLErrorDomain
code:[((NSHTTPURLResponse *)response) statusCode]
userInfo:nil];
[delegate performSelector:@selector(imageDownloader:didFailWithError:) withObject:self withObject:error];
SDWIRelease(error);
}
self.connection = nil;
self.imageData = nil;
}
}
- 下載器代理漸進(jìn)下載回調(diào)
- (void)connection:(NSURLConnection *)aConnection didReceiveData:(NSData *)data{
[imageData appendData:data];
//-----------------------------2.7版本更新-功能優(yōu)化-------------------------
if (&CGImageSourceCreateImageAtIndex == NULL){
//ImageIO在iOS < 4中不存在
self.progressive = NO;
}
if (self.progressive && expectedSize > 0 && [delegate respondsToSelector:@selector(imageDownloader:didUpdatePartialImage:)]){
//以下代碼來(lái)自http://www.cocoaintheshell.com/2011/05/progressies-download-imageio/
//感謝作者@Nyx0uf
//獲取下載的總字節(jié)數(shù)
const NSUInteger totalSize = [imageData length];
//更新數(shù)據(jù)源時(shí),我們必須傳遞所有數(shù)據(jù)险胰,而不僅僅是新字節(jié)
CGImageSourceRef imageSource = CGImageSourceCreateIncremental(NULL);
#if __has_feature(objc_arc)
CGImageSourceUpdateData(imageSource, (__bridge CFDataRef)imageData, totalSize == expectedSize);
#else
CGImageSourceUpdateData(imageSource, (CFDataRef)imageData, totalSize == expectedSize);
#endif
if (width + height == 0){
CFDictionaryRef properties = CGImageSourceCopyPropertiesAtIndex(imageSource, 0, NULL);
if (properties){
CFTypeRef val = CFDictionaryGetValue(properties, kCGImagePropertyPixelHeight);
if (val) CFNumberGetValue(val, kCFNumberLongType, &height);
val = CFDictionaryGetValue(properties, kCGImagePropertyPixelWidth);
if (val) CFNumberGetValue(val, kCFNumberLongType, &width);
CFRelease(properties);
}
}
if (width + height > 0 && totalSize < expectedSize){
//創(chuàng)建圖像
CGImageRef partialImageRef = CGImageSourceCreateImageAtIndex(imageSource, 0, NULL);
#ifdef TARGET_OS_IPHONE
//iOS變形圖像的變通方法
if (partialImageRef){
const size_t partialHeight = CGImageGetHeight(partialImageRef);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef bmContext = CGBitmapContextCreate(NULL, width, height, 8, width * 4, colorSpace, kCGBitmapByteOrderDefault | kCGImageAlphaPremultipliedFirst);
CGColorSpaceRelease(colorSpace);
if (bmContext){
CGContextDrawImage(bmContext, (CGRect){.origin.x = 0.0f, .origin.y = 0.0f, .size.width = width, .size.height = partialHeight}, partialImageRef);
CGImageRelease(partialImageRef);
partialImageRef = CGBitmapContextCreateImage(bmContext);
CGContextRelease(bmContext);
} else {
CGImageRelease(partialImageRef);
partialImageRef = nil;
}
}
#endif
if (partialImageRef){
UIImage *image = SDScaledImageForPath(url.absoluteString, [UIImage imageWithCGImage:partialImageRef]);
[[SDWebImageDecoder sharedImageDecoder] decodeImage:image
withDelegate:self
userInfo:[NSDictionary dictionaryWithObject:@"partial" forKey:@"type"]];
CGImageRelease(partialImageRef);
}
}
CFRelease(imageSource);
}
//----------------------------------end----------------------------------
}
- (void)imageDecoder:(SDWebImageDecoder *)decoder didFinishDecodingImage:(UIImage *)image userInfo:(NSDictionary *)aUserInfo{
//-----------------------------2.7版本更新-功能優(yōu)化-------------------------
if ([[aUserInfo valueForKey:@"type"] isEqualToString:@"partial"]){
[delegate imageDownloader:self didUpdatePartialImage:image];
} else {
[delegate performSelector:@selector(imageDownloader:didFinishWithImage:) withObject:self withObject:image];
}
//----------------------------------end----------------------------------
}
4. SDImageCache
- 增加緩存監(jiān)控
//---------------2.7版本更新-新增功能--------------------
//設(shè)置全局最大緩存年齡
+ (void) setMaxCacheAge:(NSInteger) maxCacheAge;
//獲取磁盤緩存中的映像數(shù)
- (int)getDiskCount;
//獲取內(nèi)存緩存中圖像的總大小
- (int)getMemorySize;
//獲取內(nèi)存緩存中的圖像數(shù)量
- (NSUInteger)getMemoryCount;
//---------------------------end----------------------
- 緩存釋放優(yōu)化
//---------------2.7版本更新-新增功能-內(nèi)存--------------------
static natural_t minFreeMemLeft = 1024*1024*12; // reserve 12MB RAM
// inspired by http://stackoverflow.com/questions/5012886/knowing-available-ram-on-an-ios-device
//確定iOS設(shè)備上的可用RAM量
static natural_t get_free_memory(void){
mach_port_t host_port;
mach_msg_type_number_t host_size;
vm_size_t pagesize;
host_port = mach_host_self();
host_size = sizeof(vm_statistics_data_t) / sizeof(integer_t);
host_page_size(host_port, &pagesize);
vm_statistics_data_t vm_stat;
if (host_statistics(host_port, HOST_VM_INFO, (host_info_t)&vm_stat, &host_size) != KERN_SUCCESS){
NSLog(@"Failed to fetch vm statistics");
return 0;
}
//統(tǒng)計(jì)數(shù)據(jù)以字節(jié)為單位
natural_t mem_free = vm_stat.free_count * pagesize;
return mem_free;
}
//---------------------------end----------------------
*********
- (void)storeImage:(UIImage *)image imageData:(NSData *)data forKey:(NSString *)key toDisk:(BOOL)toDisk{
if (!image || !key){
return;
}
//-----------------------2.7版本更新-功能優(yōu)化-----------------------
if (get_free_memory() < minFreeMemLeft){
[memCache removeAllObjects];
}
//------------------------------end------------------------------
[memCache setObject:image forKey:key];
if (toDisk){
NSArray *keyWithData;
if (data){
keyWithData = [NSArray arrayWithObjects:key, data, nil];
} else{
keyWithData = [NSArray arrayWithObjects:key, nil];
}
NSInvocationOperation *operation = SDWIReturnAutoreleased([[NSInvocationOperation alloc] initWithTarget:self
selector:@selector(storeKeyWithDataToDisk:)
object:keyWithData]);
[cacheInQueue addOperation:operation];
}
}
- (UIImage *)imageFromKey:(NSString *)key fromDisk:(BOOL)fromDisk{
if (key == nil){
return nil;
}
UIImage *image = [memCache objectForKey:key];
if (!image && fromDisk){
image = SDScaledImageForPath(key, [NSData dataWithContentsOfFile:[self cachePathForKey:key]]);
if (image){
//-----------------------2.7版本更新-功能優(yōu)化-----------------------
if (get_free_memory() < minFreeMemLeft){
[memCache removeAllObjects];
}
//------------------------------end------------------------------
[memCache setObject:image forKey:key];
}
}
return image;
}
- (void)notifyDelegate:(NSDictionary *)arguments{
NSString *key = [arguments objectForKey:@"key"];
id <SDImageCacheDelegate> delegate = [arguments objectForKey:@"delegate"];
NSDictionary *info = [arguments objectForKey:@"userInfo"];
UIImage *image = [arguments objectForKey:@"image"];
if (image){
//-----------------------2.7版本更新-功能優(yōu)化-----------------------
if (get_free_memory() < minFreeMemLeft){
[memCache removeAllObjects];
}
//------------------------------end------------------------------
[memCache setObject:image forKey:key];
if ([delegate respondsToSelector:@selector(imageCache:didFindImage:forKey:userInfo:)]){
[delegate imageCache:self didFindImage:image forKey:key userInfo:info];
}
} else {
if ([delegate respondsToSelector:@selector(imageCache:didNotFindImageForKey:userInfo:)]){
[delegate imageCache:self didNotFindImageForKey:key userInfo:info];
}
}
}
//----------------------2.7版本更新-新增功能------------------------
+ (void) setMaxCacheAge:(NSInteger)maxCacheAge{
cacheMaxCacheAge = maxCacheAge;
}
- (int)getDiskCount{
int count = 0;
NSDirectoryEnumerator *fileEnumerator = [[NSFileManager defaultManager] enumeratorAtPath:diskCachePath];
for (NSString *fileName in fileEnumerator){
count += 1;
}
return count;
}
- (int)getMemorySize{
int size = 0;
for(id key in [memCache allKeys]){
UIImage *img = [memCache valueForKey:key];
size += [UIImageJPEGRepresentation(img, 0) length];
}
return size;
}
- (NSUInteger)getMemoryCount{
return [[memCache allKeys] count];
}
//----------------------------end--------------------------------
5. SDWebImagePrefetcher
- 增加下載模式支持
//--------------------2.7版本更新-圖片下載---------------------
@property (nonatomic, assign) SDWebImageOptions options;
//----------------------------end---------------------------
//---------------2.7版本更新-新增功能----------------
@synthesize options;
//----------------------end-----------------------
+ (SDWebImagePrefetcher *)sharedImagePrefetcher{
if (instance == nil){
instance = [[SDWebImagePrefetcher alloc] init];
instance.maxConcurrentDownloads = 3;
//---------------2.7版本更新-新增功能----------------
instance.options = (SDWebImageLowPriority);
//----------------------end-----------------------
}
return instance;
}
6. SDWebImageCompat
- 針對(duì)圖片數(shù)據(jù)類型兼容
NS_INLINE UIImage *SDScaledImageForPath(NSString *path, NSObject *imageOrData){
if (!imageOrData){
return nil;
}
//---------------------2.7版本更新-代碼優(yōu)化---------------------
UIImage *image = nil;
if ([imageOrData isKindOfClass:[NSData class]]){
image = [[UIImage alloc] initWithData:(NSData *)imageOrData];
} else if ([imageOrData isKindOfClass:[UIImage class]]){
image = SDWIReturnRetained((UIImage *)imageOrData);
} else {
return nil;
}
//----------------------------end----------------------------
if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)]){
CGFloat scale = 1.0;
if (path.length >= 8){
NSRange range = [path rangeOfString:@"@2x." options:0 range:NSMakeRange(path.length - 8, 5)];
if (range.location != NSNotFound){
scale = 2.0;
}
}
UIImage *scaledImage = [[UIImage alloc] initWithCGImage:image.CGImage scale:scale orientation:UIImageOrientationUp];
SDWISafeRelease(image)
image = scaledImage;
}
return SDWIReturnAutoreleased(image);
}