SDWebImage前世今生之V2.0版本

2019-03-07  本文已影响0人  _相信自己_

2.0版本2010年6月9日发布

2.0版本类结构上没有发生改变,最大改变增加了NSURLConnection网络请求和下面的一些优化

1. SDWebImageDownloaderDelegate.h 新增错误回调

@protocol SDWebImageDownloaderDelegate <NSObject>
@optional

- (void)imageDownloader:(SDWebImageDownloader *)downloader didFinishWithImage:(UIImage *)image;

//-----------------------2.0版本更新-新增错误回调-----------------------
- (void)imageDownloader:(SDWebImageDownloader *)downloader didFailWithError:(NSError *)error;
//---------------------------------end------------------------------

@end

2. SDWebImageManager.m去掉downloadWithURL、cancelForDelegate、didFinishWithImage方法的同步代码块

 - (void)downloadWithURL:(NSURL *)url delegate:(id<SDWebImageManagerDelegate>)delegate{
    if (url == nil || [failedURLs containsObject:url]){
        return;
    }
    SDWebImageDownloader *downloader = [downloaderForURL objectForKey:url];
    if (!downloader){
        downloader = [SDWebImageDownloader downloaderWithURL:url delegate:self];
        [downloaderForURL setObject:downloader forKey:url];
    }
//-----------------------2.0版本更新-去除@synchronized同步块-----------------------
    [delegates addObject:delegate];
    [downloaders addObject:downloader];
//-----------------------------------end-----------------------------
}

- (void)cancelForDelegate:(id<SDWebImageManagerDelegate>)delegate{
//-----------------------2.0版本更新-去除@synchronized同步块-----------------------
    NSUInteger idx = [delegates indexOfObjectIdenticalTo:delegate];
    if (idx == NSNotFound){
        return;
    }
    SDWebImageDownloader *downloader = [downloaders objectAtIndex:idx];
    [delegates removeObjectAtIndex:idx];
    [downloaders removeObjectAtIndex:idx];
    if (![downloaders containsObject:downloader]){
        [downloader cancel];
        [downloaderForURL removeObjectForKey:downloader.url];
    }
//-----------------------------------end-----------------------------
}

- (void)imageDownloader:(SDWebImageDownloader *)downloader didFinishWithImage:(UIImage *)image{
//-----------------------2.0版本更新-去除@synchronized同步块-----------------------
    for (NSInteger idx = [downloaders count] - 1; idx >= 0; idx--){
        SDWebImageDownloader *aDownloader = [downloaders objectAtIndex:idx];
        if (aDownloader == downloader){
            id<SDWebImageManagerDelegate> delegate = [delegates objectAtIndex:idx];
            if (image && [delegate respondsToSelector:@selector(webImageManager:didFinishWithImage:)]){
                [delegate performSelector:@selector(webImageManager:didFinishWithImage:) withObject:self withObject:image];
            }
            [downloaders removeObjectAtIndex:idx];
            [delegates removeObjectAtIndex:idx];
        }
    }
//-----------------------------------end-----------------------------

    if (image){
        [[SDImageCache sharedImageCache] storeImage:image forKey:[downloader.url absoluteString]];
    } else {
        [failedURLs addObject:downloader.url];
    }
    [downloaderForURL removeObjectForKey:downloader.url];
}

3. SDWebImageDownloader.h 的父类由NSOperation更新为NSObject,同时添加了NSURLConnection成员变量。

//-----------------------2.0版本更新-新增网络请求,继承自NSObject-----------------------
@interface SDWebImageDownloader : NSObject{
@private
    NSURL *url;
    NSURLConnection *connection;
    NSMutableData *imageData;
}
//-------------------------------end--------------------------------

@property (nonatomic, retain) NSURL *url;
@property (nonatomic, assign) id<SDWebImageDownloaderDelegate> delegate;

+ (id)downloaderWithURL:(NSURL *)url delegate:(id<SDWebImageDownloaderDelegate>)delegate;

//--------------2.0版本更新-新增网络请求,废弃setMaxConcurrentDownloads方法-----------------------
+ (void)setMaxConcurrentDownloads:(NSUInteger)max __attribute__((deprecated));
- (void)start;
- (void)cancel;
//-------------------------------end--------------------------------
@end

4. SDWebImageDownloader.m增加开始和取消网络请求方法start 、cancel和网络请求回调方法didReceiveData、connectionDidFinishLoading、didFailWithError

//--------------------------2.0版本更新-网络请求--------------------------
@interface SDWebImageDownloader ()
@property (nonatomic, retain) NSURLConnection *connection;
@property (nonatomic, retain) NSMutableData *imageData;
@end
//--------------------------------end---------------------------------

@implementation SDWebImageDownloader
@synthesize url, delegate, connection, imageData;

//--------------------------2.0版本更新-去除NSOperationQueue--------------------------
+ (id)downloaderWithURL:(NSURL *)url delegate:(id<SDWebImageDownloaderDelegate>)delegate{
    SDWebImageDownloader *downloader = [[SDWebImageDownloader alloc] init];
    downloader.url = url;
    downloader.delegate = delegate;
    [downloader start];
    return downloader;
}
//--------------------------------end---------------------------------

+ (void)setMaxConcurrentDownloads:(NSUInteger)max{
    // NOOP
}

//--------------------------2.0版本更新-网络请求--------------------------
- (void)start{
    NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:15];
    self.connection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:NO];
    [connection scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
    [connection start];

    if (connection){
        self.imageData = [NSMutableData data];
    } else {
        if ([delegate respondsToSelector:@selector(imageDownloader:didFailWithError:)]){
            [delegate performSelector:@selector(imageDownloader:didFailWithError:) withObject:self withObject:nil];
        }
    }
}
- (void)cancel{
    if (connection){
        [connection cancel];
        self.connection = nil;
    }
}
//--------------------------end--------------------------

//--------------------------2.0版本更新-请求回调--------------------------
- (void)connection:(NSURLConnection *)aConnection didReceiveData:(NSData *)data{
    [imageData appendData:data];
}

- (void)connectionDidFinishLoading:(NSURLConnection *)aConnection{
    UIImage *image = [[UIImage alloc] initWithData:imageData];
    self.imageData = nil;
    self.connection = nil;
    if ([delegate respondsToSelector:@selector(imageDownloader:didFinishWithImage:)]){
        [delegate performSelector:@selector(imageDownloader:didFinishWithImage:) withObject:self withObject:image];
    }
}

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{
    if ([delegate respondsToSelector:@selector(imageDownloader:didFailWithError:)]){
        [delegate performSelector:@selector(imageDownloader:didFailWithError:) withObject:self withObject:error];
    }
    self.connection = nil;
    self.imageData = nil;
}
//--------------------------end--------------------------

@end

5. SDImageCache.m新增后台通知UIApplicationDidEnterBackgroundNotification,当进入后台模式清空内存缓存,优化内存存储。

- (instancetype)init{
    self = [super init];
    if (self) {
        //内存缓存
        memCache = [[NSMutableDictionary alloc] init];
        //磁盘缓存
        NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
        //磁盘目录
        diskCachePath = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"ImageCache"];
        //创建目录
        if (![[NSFileManager defaultManager] fileExistsAtPath:diskCachePath]){
            [[NSFileManager defaultManager] createDirectoryAtPath:diskCachePath withIntermediateDirectories:YES attributes:nil error:NULL];
        }
        
        //初始化缓存队列
        cacheInQueue = [[NSOperationQueue alloc] init];
        cacheInQueue.maxConcurrentOperationCount = 2;
        //订阅应用程序事件
        //应用程序终止,里面回调didReceiveMemoryWarning方法,清空内存
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(didReceiveMemoryWarning:)
                                                     name:UIApplicationDidReceiveMemoryWarningNotification
                                                   object:nil];
        //应用程序终止,里面回调willTerminate方法,清空磁盘
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(willTerminate)
                                                     name:UIApplicationWillTerminateNotification
                                                   object:nil];

        //-----------------------2.0版本更新-新增后台通知-----------------------
        UIDevice *device = [UIDevice currentDevice];
        if ([device respondsToSelector:@selector(isMultitaskingSupported)] && device.multitaskingSupported){
            [[NSNotificationCenter defaultCenter] addObserver:self
                                                     selector:@selector(clearMemory)
                                                         name:UIApplicationDidEnterBackgroundNotification
                                                       object:nil];
        }
        //--------------------------------end--------------------------------
    }
    return self;
}
上一篇下一篇

猜你喜欢

热点阅读