IOS开发网络加载图片缓存策略之──ASIDownloadCache缓存策略

来源:互联网 发布:ios数据存储方式 编辑:程序博客网 时间:2024/04/30 16:30

转载自:http://www.cnblogs.com/pengyingh/articles/2343061.html

IOS开发网络加载图片缓存策略之──ASIDownloadCache缓存策略

在我们实际工程中,很多情况需要从网络上加载图片,然后将图片在imageview中显示出来,但每次都要从网络上请求,会严重影响用户体验,为了不是每次显示都需要从网上下载数据,希望将图片放到本地缓存,因此我们需要一个好的的缓存策略,今天我将我在项目工程中的实际经验分享给大家,我这里主要介绍一下强大的ASIHTTPRequest的缓存策略,以及使用方法:

 

    下面是具体步骤:

一、设置缓存策略

    首先在SplitDemoAppDelegate委托代理中,实现如下代码:

    在SplitDemoAppDelegate.h文件中,代码如下:

 

复制代码
 1 #import <UIKit/UIKit.h> 2  3 @class ASIDownloadCache; 4  5 @interface SplitDemoAppDelegate : NSObject <UIApplicationDelegate,UITabBarControllerDelegate> { 6  7     UIWindow *_window; 8  9     ASIDownloadCache*_downloadCache;            //下载缓存策略10 11 }12 13 @property (nonatomic, retain) ASIDownloadCache*downloadCache;14 15 @end
复制代码

 

在SplitDemoAppDelegate.m文件中,代码如下:

复制代码
 1 #import "SplitDemoAppDelegate.h" 2  3 @implementation SplitDemoAppDelegate 4  5 @synthesize window=_window; 6  7 @synthesize downloadCache = _downloadCache; 8  9 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions10 11 {12 13     //初始化ASIDownloadCache缓存对象14 15    ASIDownloadCache *cache = [[ASIDownloadCache alloc] init];16 17    self.downloadCache = cache;18 19   [cache release];20 21 22    //路径23 24    NSArray *paths =NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);25 26   NSString *documentDirectory = [paths objectAtIndex:0];27 28    //设置缓存存放路径29 30    [self.downloadCache setStoragePath:[documentDirectorystringByAppendingPathComponent:@"resource"]];31 32    //设置缓存策略33 34     [self.downloadCache setDefaultCachePolicy:ASIOnlyLoadIfNotCachedCachePolicy];35 36     // Override point for customization after application launch.37 38     [self.window makeKeyAndVisible];39 40     return YES;41 42 }43 44 45 - (void)dealloc46 47 {48 49     [_window release];50 51     [_downloadCache release];52 53    [super dealloc];54 55 }56 57 @end
复制代码

 

    二、创建缓存线程

    这一步是创建一个NSOperation类,实现缓存的方法,代码如下:

    ResourceContainer.h文件实现:

 

复制代码
 1 #import <Foundation/Foundation.h> 2  3 #import "ASIHTTPRequest.h" 4  5 #import "SplitDemoAppDelegate.h" 6  7   8  9 @interface ResourceContainer : NSOperation {10 11 NSURL*_resourceURL;            //资源请求url12 13 NSObject*_hostObject;             14 15 SEL_resourceDidReceive;      //资源接手响应方法  16 17 SplitDemoAppDelegate*_appDelegate;            //应用委托对象18 19 ASIHTTPRequest*_httpRequest;            20 21 UIImageView*_imageView;              22 23 }24 25  26 27 @property (nonatomic, retain) NSURL*resourceURL;28 29 @property (nonatomic, retain) NSObject*hostObject;30 31 @property (nonatomic, assign) SELresourceDidReceive;32 33 @property (nonatomic, assign) SplitDemoAppDelegate   *appDelegate;34 35 @property (nonatomic, retain) ASIHTTPRequest*httpRequest;36 37 @property (nonatomic, retain) UIImageView*imageView;38 39  40 41 //http请求回调方法42 43 -(void)didStartHttpRequest:(ASIHTTPRequest *)request;44 45 -(void)didFinishHttpRequest:(ASIHTTPRequest *)request;46 47 -(void)didFailedHttpRequest:(ASIHTTPRequest *)request;48 49  50 51 //取消资源请求52 53 -(void)cancelReourceGet;54 55 //资源接收回调方法56 57 -(void)resourceDidReceive:(NSData *)resource;58 59 @end
复制代码

 

ResourceContainer.m文件实现:

复制代码
  1 #import "ResourceContainer.h"  2 #import "HttpConstant.h"  3 #import "ASIDownloadCache.h"  4 @implementation ResourceContainer  5 @synthesize resourceURL = _resourceURL;  6 @synthesize hostObject = _hostObject;  7 @synthesize resourceDidReceive = _resourceDidReceive;  8 @synthesize appDelegate = _appDelegate;  9 @synthesize httpRequest = _httpRequest; 10 @synthesize imageView = _imageView; 11  12 -(id)init{ 13  14      if(self == [super init]){ 15  16      self.appDelegate = (SplitDemoAppDelegate *)[[UIApplication        sharedApplication] delegate]; 17  18       } 19  20    return self; 21  22 } 23  24  25 -(void)main{ 26  27       if(self.hostObject == nil) 28       return; 29  30      if(self.resourceURL == nil){ 31           [self resourceDidReceive:nil]; 32           return; 33      } 34  35       ASIHTTPRequest *request = [ASIHTTPRequest     requestWithURL:self.resourceURL] 36       self.httpRequest = request; 37  38   39  40 [self.httpRequest setDownloadCache:self.appDelegate.downloadCache]; 41 [self.httpRequest setDelegate:self]; 42 [self.httpRequest setDidStartSelector:@selector(didStartHttpRequest:)]; 43 [self.httpRequest setDidFinishSelector:@selector(didFinishHttpRequest:)]; 44 [self.httpRequest setDidFailSelector:@selector(didFailedHttpRequest:)]; 45  46     //发异步请求 47  48 [self.httpRequest startAsynchronous]; 49  50 } 51  52 - (void)dealloc { 53  54 [_resourceURL release]; 55 [_hostObject release]; 56 [_httpRequest release]; 57 [_imageView release]; 58 [super dealloc]; 59  60 } 61  62 //开始请求 63  64 -(void)didStartHttpRequest:(ASIHTTPRequest *)request{ 65  66 [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES]; 67  68 } 69  70 //请求成功返回处理结果 71  72 -(void)didFinishHttpRequest:(ASIHTTPRequest *)request{ 73  74 [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO]; 75  76   77  78     if([request responseStatusCode] == 200 || [request responseStatusCode] == 304){ 79  80 //判断是否来自缓存 81  82         if([request didUseCachedResponse]){ 83  84 NSLog(@"=========资源请求:%@ 来自缓存============",[self.resourceURL absoluteURL]); 85  86         } 87          else{ 88  89             NSLog(@"=========资源请求:图片不来自缓存============"); 90         } 91  92  93      [self resourceDidReceive:[request responseData]]; 94  95 } 96  97 else { 98  99        [self resourceDidReceive:nil];100 101        }102 103 }104 105 //失败请求返回处理结果106 107 -(void)didFailedHttpRequest:(ASIHTTPRequest *)request{108 109 [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];110 111 [self resourceDidReceive:nil];112 113 }114 115 //取消资源请求116 117 -(void)cancelReourceGet{118 119 [self.httpRequest cancel];120 121 }122 123 //资源接收处理方法124 125 -(void)resourceDidReceive:(NSData *)resource{126 127 if([self.hostObject respondsToSelector:self.resourceDidReceive]){128 129 if(resource != nil && self.imageView != nil){130 131 self.imageView.image = [UIImage imageWithData:resource];132 133 }134 135 136 [self.hostObject performSelectorOnMainThread:self.resourceDidReceive withObject:self.imageViewwaitUntilDone:NO];137 138 }139 140 }141 142 @end 
复制代码

 

    到第二步,我们的缓存策略的设置,以及资源请求和接收数据方法已经构建完毕,下面介绍一下如何使用我们上面创建的NSOperation类

 

    三、图片请求(利用上面创建的类)

    这里以我的工程为例进行分析:

在DetailViewController.h声明文件中:

 

复制代码
 1 #import <UIKit/UIKit.h> 2  3 @interface DetailViewController :UIViewController { 4  5     NSURL                         *_imageURL;                    //图片url 6  7     NSMutableArray            *_originalIndexArray;        //保存请求图片的号 8  9     NSMutableDictionary     *_originalOperationDic;     //保存图片请求队列10 11     NSOperationQueue        *_requestImageQueue;    //图片请求队列12 13 }14 15 @property (nonatomic, retain) NSURL                       *imageURL;16 @property (nonatomic, retain) NSMutableArray          *originalIndexArray;17 @property (nonatomic, retain) NSMutableDictionary   *originalOperationDic;18 @property (nonatomic, retain) NSOperationQueue      * requestImageQueue;19 20 //显示图片信息21 22 -(void)displayProductImage;23 24 //根据图片序号显示请求图片资源25 26 -(void)displayImageByIndex:(NSInteger)index ByImageURL:(NSURL *)url;27 28 //处理图片请求返回信息29 30 -(void)imageDidReceive:(UIImageView *)imageView;31 32 @end
复制代码



 

 在DetailViewController.m实现文件中:

复制代码
  1 #import "ProductDetailViewController.h"  2   3 //这里引入在第二步中,我们创建的对象  4 #import "ResourceContainer.h"  5   6 @implementation DetailViewController  7 @synthesize imageURL = _imageURL;  8 @synthesize originalIndexArray = _originalIndexArray;  9 @synthesize originalOperationDic = _originalOperationDic; 10 @synthesize requestImageQueue = _requestImageQueue; 11  12  13 - (void)viewDidLoad 14  15 { 16  17      [super viewDidLoad]; 18      NSOperationQueue *tempQueue = [[NSOperationQueue alloc] init]; 19  20      self.requsetImageQueue = tempQueue; 21      [tempQueue release]; 22  23       NSMutableArray *array = [[NSMutableArray alloc] init]; 24  25       self.originalIndexArray = array; 26       [array release]; 27  28        NSMutableDictionary *dic = [[NSMutableDictionary alloc] init]; 29  30        self.originalOperationDic = dic; 31        [dic release]; 32  33 } 34  35 //显示图片信息 36  37 -(void)displayProductImage 38  39 { 40  41     NSURL *url = [NSURL URLWithString:@"http://xxx.xxx.xxx.xxx"]; 42  43     //这个是从器返回有图片数目,self.xxxx根据具体的场合 44  45     int imageCount = [self.xxxx.imageNum intValue]; 46  47     for (int i=0; i<imageCount; i++) { 48  49         NSString *str1 = @"这里是拼图片请求url,根据实际需求"; 50  51         self.imageURL = [url URLByAppendingPathComponent:str1]; 52  53         //根据图片号请求资源 54  55         [self displayImageByIndex:i ByImageURL:self.productImageURL]; 56  57     } 58  59 } 60  61 //根据图片序号显示请求图片资源 62  63 -(void) displayImageByIndex:(NSInteger)index ByImageURL:(NSURL *)url 64  65 { 66  67     NSString *indexForString = [NSString stringWithFormat:@"%d",index]; 68  69     //若数组中已经存在该图片编号,说明图片加载完毕,直接返回 70  71     if ([self.originalIndexArray containsObject:indexForString]) { 72  73          return; 74  75     } 76  77     //创建UIImageView对象 78  79     UIImageView *imageView = [[UIImageView alloc] init]; 80  81     imageView.tag = index; 82  83     //创建资源请求对象 84  85     ResourceContainer  *imageOperation = [[ResourceContainer alloc] init]; 86  87     imageOperation.resourceURL = url; 88  89     imageOperation.hostObject = self; 90  91     //设置收到图片信息处理理方法 92  93     imageOperation.resourceDidReceive = @selector(imageDidReceive:); 94  95     imageOperation.imageView = imageView; 96  97     [imageView release]; 98  99     //将图片请求对象加入图片请求队列中100 101     [self.requsetImageQueue addOperation:imageOperation];102 103     [self.originalOperationDic setObject:imageOperation forKey:indexForString];104 105     [imageOperation release];106 107 }108 109 //处理图片请求返回信息110 111 -(void)imageDidReceive:(UIImageView *)imageView112 113 {114 115     if (imageView == nil||imageView.image == nil) {116 117             imageView.image = [UIImage imageNamed:@"no-pic-300-250.png"];118 119      }120 121     //将图片信息加载到前台,self.openFlowView是我用的coverFlow,coverFlow的使用方法网上很多,自己找吧122 123     [self.openFlowView setImage:imageView.image forIndex:imageView.tag];124 125     [self.originalIndexArray addObject:[NSString stringWithFormat:@"%d",imageView.tag]];126 127     [self.originalOperationDic removeObjectForKey:[NSString stringWithFormat:@"%d",imageView.tag]];128 129 }130 131 - (void)dealloc132 133 {134      [_requestImageQueue release];135 136      [_originalIndexArray release];137 138      [_originalOperationDic release];139 140      [_imageURL release];141 142      [super dealloc];143 144 }145 146 @end
复制代码


    经过上述步骤,我们实现了加载网络图片时缓存功能,增强了用户体验效果。代码中可能会有诸多问题,希望网友指教,有更好的缓存方法,也希望一起交流!


原创粉丝点击