【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 
 4 @implementation SplitDemoAppDelegate
 5 
 6 
 7 @synthesize window=_window;
 8 
 9 
10 @synthesize downloadCache = _downloadCache;
11 
12 
13 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
14 
15 {
16 
17     //初始化ASIDownloadCache缓存对象
18 
19    ASIDownloadCache *cache = [[ASIDownloadCache alloc] init];
20 
21    self.downloadCache = cache;
22 
23   [cache release];
24 
25  
26 
27    //路径
28 
29    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);
30 
31   NSString *documentDirectory = [paths objectAtIndex:0];
32 
33  
34 
35    //设置缓存存放路径
36 
37    [self.downloadCache setStoragePath:[documentDirectory stringByAppendingPathComponent:@"resource"]];
38 
39    //设置缓存策略
40 
41     [self.downloadCache setDefaultCachePolicy:ASIOnlyLoadIfNotCachedCachePolicy];
42 
43     // Override point for customization after application launch.
44 
45     [self.window makeKeyAndVisible];
46 
47     return YES;
48 
49 }
50 
51 - (void)dealloc
52 
53 {
54 
55     [_window release];
56 
57     [_downloadCache release];
58 
59    [super dealloc];
60 
61 }
62 
63 @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;            //资源请求url
12 
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) SEL resourceDidReceive;
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  
60 
61 @end

 

    ResourceContainer.m文件实现:

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

 

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

 

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

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

    在DetailViewController.h声明文件中,

 

 1 #import <UIKit/UIKit.h>
 2 
 3 
 4 @interface DetailViewController :UIViewController {
 5 
 6  
 7 
 8     NSURL                          *_imageURL;                    //图片url
 9 
10     NSMutableArray            *_originalIndexArray;        //保存请求图片的号
11 
12     NSMutableDictionary     *_originalOperationDic;     //保存图片请求队列
13 
14     NSOperationQueue        *_requestImageQueue;    //图片请求队列
15 
16  
17 
18 }
19 
20  
21 
22 @property (nonatomic, retain) NSURL                        *imageURL;
23 
24 @property (nonatomic, retain) NSMutableArray          *originalIndexArray;
25 
26 @property (nonatomic, retain) NSMutableDictionary   *originalOperationDic;
27 
28 @property (nonatomic, retain) NSOperationQueue      * requestImageQueue;
29 
30  
31 
32  
33 
34  
35 
36 //显示图片信息
37 
38 -(void)displayProductImage;
39 
40 //根据图片序号显示请求图片资源
41 
42 -(void)displayImageByIndex:(NSInteger)index ByImageURL:(NSURL *)url;
43 
44  
45 
46 //处理图片请求返回信息
47 
48 -(void)imageDidReceive:(UIImageView *)imageView;
49 
50  
51 
52  
53 
54  
55 
56 @end

 

     在DetailViewController.m实现文件中,

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

 

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

posted @ 2014-09-07 22:27  Danny_吕昌辉  阅读(552)  评论(0编辑  收藏  举报