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*)launchOptions
10
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)dealloc
46
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; //資源請求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) 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 *)imageView
112
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)dealloc
132
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


    經過上述步驟,我們實現了加載網絡圖片時緩存功能,增強了用戶體驗效果。代碼中可能會有諸多問題,希望網友指教,有更好的緩存方法,也希望一起交流!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM