用NSOperation写下载队列
说明
1. 支持缓存机制
2. 图片都是在主线程中加载
3. 文件名用了md5加密
*这东西被人写烂了,但大伙如果对NSOperation不熟悉的话,可以看看本人的实现.
源码
https://github.com/YouXianMing/NSOperationExample
// // ImageDownloadOperation.h // NSOperationDownloadImage // // Created by YouXianMing on 15/9/7. // Copyright (c) 2015年 YouXianMing. All rights reserved. // #import <Foundation/Foundation.h> @class ImageDownloadOperation; @protocol ImageDownloadOperationDelegate <NSObject> @required - (void)imageDownloadOperation:(ImageDownloadOperation *)operation data:(NSData *)data; @end @interface ImageDownloadOperation : NSOperation { BOOL _executing; BOOL _finished; } /** * 代理 */ @property (nonatomic, weak) id <ImageDownloadOperationDelegate> delegate; /** * 图片地址 */ @property (nonatomic, strong) NSString *imageUrlString; /** * 便利构造器 * * @param urlString 图片地址 * @param delegate 代理 * * @return 实例对象 */ + (instancetype)operationWithImageUrlString:(NSString *)urlString delegate:(id <ImageDownloadOperationDelegate>)delegate; @end
// // ImageDownloadOperation.m // NSOperationDownloadImage // // Created by YouXianMing on 15/9/7. // Copyright (c) 2015年 YouXianMing. All rights reserved. // #import "ImageDownloadOperation.h" #import <CommonCrypto/CommonDigest.h> @interface ImageDownloadOperation () @property (nonatomic, strong) NSURLConnection *connection; @property (nonatomic, strong) NSString *md5String; @property (nonatomic, strong) NSString *filePathString; @end @implementation ImageDownloadOperation - (void)main { // 验证图片地址是否为空 if (_imageUrlString.length <= 0) { [self delegateEventWithData:nil]; [self completeOperation]; return; } // 生成文件路径 self.md5String = [self MD5HashWithString:_imageUrlString]; self.filePathString = [self pathWithFileName:self.md5String]; // 文件如果存在则直接读取 BOOL exist = [[NSFileManager defaultManager] fileExistsAtPath:self.filePathString isDirectory:nil]; if (exist) { [self delegateEventWithData:[NSData dataWithContentsOfFile:self.filePathString]]; [self completeOperation]; return; } NSURL *url = [NSURL URLWithString:_imageUrlString]; NSURLRequest *request = [NSURLRequest requestWithURL:url]; self.connection = [NSURLConnection connectionWithRequest:request delegate:self]; // 让线程不结束 do { @autoreleasepool { [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; if (self.isCancelled) { [self completeOperation]; } } } while (self.isExecuting && self.isFinished == NO); } #pragma mark - 网络代理 - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { } - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { [self writeData:data toPath:self.filePathString]; [self delegateEventWithData:data]; } - (void)connectionDidFinishLoading:(NSURLConnection *)connection { [self completeOperation]; } - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { [self delegateEventWithData:nil]; [self completeOperation]; } #pragma mark - + (instancetype)operationWithImageUrlString:(NSString *)urlString delegate:(id <ImageDownloadOperationDelegate>)delegate { ImageDownloadOperation *operation = [[ImageDownloadOperation alloc] init]; operation.delegate = delegate; operation.imageUrlString = urlString; return operation; } #pragma mark - - (void)completeOperation { [self willChangeValueForKey:@"isFinished"]; [self willChangeValueForKey:@"isExecuting"]; _executing = NO; _finished = YES; [self didChangeValueForKey:@"isExecuting"]; [self didChangeValueForKey:@"isFinished"]; } - (void)start { if ([self isCancelled]) { [self willChangeValueForKey:@"isFinished"]; _finished = YES; [self didChangeValueForKey:@"isFinished"]; return; } [self willChangeValueForKey:@"isExecuting"]; [NSThread detachNewThreadSelector:@selector(main) toTarget:self withObject:nil]; _executing = YES; [self didChangeValueForKey:@"isExecuting"]; } - (BOOL)isExecuting { return _executing; } - (BOOL)isFinished { return _finished; } - (BOOL)isConcurrent { return YES; } #pragma mark - - (NSString *)MD5HashWithString:(NSString *)string { CC_MD5_CTX md5; CC_MD5_Init(&md5); CC_MD5_Update(&md5, [string UTF8String], (CC_LONG) [string length]); unsigned char digest[CC_MD5_DIGEST_LENGTH]; CC_MD5_Final(digest, &md5); NSString *s = [NSString stringWithFormat: @"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", digest[0], digest[1], digest[2], digest[3], digest[4], digest[5], digest[6], digest[7], digest[8], digest[9], digest[10], digest[11], digest[12], digest[13], digest[14], digest[15]]; return s; } - (NSString *)pathWithFileName:(NSString *)name { NSString *path = [NSString stringWithFormat:@"/Documents/%@", name]; return [NSHomeDirectory() stringByAppendingPathComponent:path]; } - (void)delegateEventWithData:(NSData *)data { if (_delegate && [_delegate respondsToSelector:@selector(imageDownloadOperation:data:)]) { dispatch_async(dispatch_get_main_queue(), ^{ [_delegate imageDownloadOperation:self data:data]; }); } } - (void)writeData:(NSData *)data toPath:(NSString *)path { dispatch_async(dispatch_get_global_queue(0, 0), ^{ [data writeToFile:path atomically:YES]; }); } @end
细节