很多情况需要从网络上加载图片,然后将图片在imageview中显示出来,但每次都要从网络上请求,会严重影响用户体验,为了不是每次显示都需要从网上下载数据,希望将图片放到本地缓存,因此我们需要一个好的的缓存策略,今天我将我在项目工程中的实际经验分享给大家,我这里主要介绍一下强大的ASIHTTPRequest的缓存策略,以及使用方法:
下面是具体步骤:
一、设置缓存策略
首先在SplitDemoAppDelegate委托代理中,实现如下代码:
在SplitDemoAppDelegate.h文件中,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| #import <UIKit/UIKit.h> @class ASIDownloadCache;
@interface SplitDemoAppDelegate : NSObject <UIApplicationDelegate,UITabBarControllerDelegate> {
UIWindow *_window;
ASIDownloadCache*_downloadCache;
}
@property (nonatomic, retain) ASIDownloadCache*downloadCache;
@end
|
在SplitDemoAppDelegate.m文件中,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| #import "SplitDemoAppDelegate.h" @implementation SplitDemoAppDelegate
@synthesize window=_window;
@synthesize downloadCache = _downloadCache;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions
{
ASIDownloadCache *cache = [[ASIDownloadCache alloc] init];
self.downloadCache = cache;
[cache release];
NSArray *paths =NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);
NSString *documentDirectory = [paths objectAtIndex:0];
[self.downloadCache setStoragePath:[documentDirectorystringByAppendingPathComponent:@"resource"]];
[self.downloadCache setDefaultCachePolicy:ASIOnlyLoadIfNotCachedCachePolicy];
[self.window makeKeyAndVisible];
return YES;
}
- (void)dealloc
{
[_window release];
[_downloadCache release];
[super dealloc];
} @end
|
二、创建缓存线程
这一步是创建一个NSOperation类,实现缓存的方法,代码如下:
ResourceContainer.h文件实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| #import <Foundation/Foundation.h>
#import "ASIHTTPRequest.h"
#import "SplitDemoAppDelegate.h"
@interface ResourceContainer : NSOperation {
NSURL*_resourceURL;
NSObject*_hostObject;
SEL_resourceDidReceive;
SplitDemoAppDelegate*_appDelegate;
ASIHTTPRequest*_httpRequest;
UIImageView*_imageView;
}
@property (nonatomic, retain) NSURL*resourceURL;
@property (nonatomic, retain) NSObject*hostObject;
@property (nonatomic, assign) SELresourceDidReceive;
@property (nonatomic, assign) SplitDemoAppDelegate *appDelegate;
@property (nonatomic, retain) ASIHTTPRequest*httpRequest;
@property (nonatomic, retain) UIImageView*imageView;
-(void)didStartHttpRequest:(ASIHTTPRequest *)request;
-(void)didFinishHttpRequest:(ASIHTTPRequest *)request;
-(void)didFailedHttpRequest:(ASIHTTPRequest *)request;
-(void)cancelReourceGet;
-(void)resourceDidReceive:(NSData *)resource;
@end
|
ResourceContainer.m文件实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
| #import "ResourceContainer.h" #import "HttpConstant.h" #import "ASIDownloadCache.h" @implementation ResourceContainer @synthesize resourceURL = _resourceURL; @synthesize hostObject = _hostObject; @synthesize resourceDidReceive = _resourceDidReceive; @synthesize appDelegate = _appDelegate; @synthesize httpRequest = _httpRequest; @synthesize imageView = _imageView;
-(id)init{
if(self == [super init]){ self.appDelegate = (SplitDemoAppDelegate *)[[UIApplication sharedApplication] delegate]; } return self; }
-(void)main{
if(self.hostObject == nil) return;
if(self.resourceURL == nil){ [self resourceDidReceive:nil]; return; }
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:self.resourceURL] self.httpRequest = request;
[self.httpRequest setDownloadCache:self.appDelegate.downloadCache]; [self.httpRequest setDelegate:self]; [self.httpRequest setDidStartSelector:@selector(didStartHttpRequest:)]; [self.httpRequest setDidFinishSelector:@selector(didFinishHttpRequest:)]; [self.httpRequest setDidFailSelector:@selector(didFailedHttpRequest:)];
[self.httpRequest startAsynchronous];
}
- (void)dealloc {
[_resourceURL release]; [_hostObject release]; [_httpRequest release]; [_imageView release]; [super dealloc];
}
-(void)didStartHttpRequest:(ASIHTTPRequest *)request{
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
}
-(void)didFinishHttpRequest:(ASIHTTPRequest *)request{
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
if([request responseStatusCode] == 200 || [request responseStatusCode] == 304){
if([request didUseCachedResponse]){ NSLog(@"=========资源请求:%@ 来自缓存============",[self.resourceURL absoluteURL]); } else{ NSLog(@"=========资源请求:图片不来自缓存============"); } [self resourceDidReceive:[request responseData]];
} else {
[self resourceDidReceive:nil];
}
}
-(void)didFailedHttpRequest:(ASIHTTPRequest *)request{
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
[self resourceDidReceive:nil];
}
-(void)cancelReourceGet{
[self.httpRequest cancel];
}
-(void)resourceDidReceive:(NSData *)resource{
if([self.hostObject respondsToSelector:self.resourceDidReceive]){
if(resource != nil && self.imageView != nil){
self.imageView.image = [UIImage imageWithData:resource];
}
[self.hostObject performSelectorOnMainThread:self.resourceDidReceive withObject:self.imageViewwaitUntilDone:NO];
}
} @end
|
到第二步,我们的缓存策略的设置,以及资源请求和接收数据方法已经构建完毕,下面介绍一下如何使用我们上面创建的NSOperation类
三、图片请求(利用上面创建的类)
这里以我的工程为例进行分析:
在DetailViewController.h声明文件中:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| #import <UIKit/UIKit.h>
@interface DetailViewController :UIViewController {
NSURL *_imageURL;
NSMutableArray *_originalIndexArray;
NSMutableDictionary *_originalOperationDic;
NSOperationQueue *_requestImageQueue;
}
@property (nonatomic, retain) NSURL *imageURL; @property (nonatomic, retain) NSMutableArray *originalIndexArray; @property (nonatomic, retain) NSMutableDictionary *originalOperationDic; @property (nonatomic, retain) NSOperationQueue * requestImageQueue;
-(void)displayProductImage;
-(void)displayImageByIndex:(NSInteger)index ByImageURL:(NSURL *)url;
-(void)imageDidReceive:(UIImageView *)imageView;
@end
|
在DetailViewController.m实现文件中:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
| #import "ProductDetailViewController.h"
#import "ResourceContainer.h"
@implementation DetailViewController @synthesize imageURL = _imageURL; @synthesize originalIndexArray = _originalIndexArray; @synthesize originalOperationDic = _originalOperationDic; @synthesize requestImageQueue = _requestImageQueue;
- (void)viewDidLoad {
[super viewDidLoad]; NSOperationQueue *tempQueue = [[NSOperationQueue alloc] init];
self.requsetImageQueue = tempQueue; [tempQueue release];
NSMutableArray *array = [[NSMutableArray alloc] init];
self.originalIndexArray = array; [array release];
NSMutableDictionary *dic = [[NSMutableDictionary alloc] init];
self.originalOperationDic = dic; [dic release];
}
-(void)displayProductImage { NSURL *url = [NSURL URLWithString:@"http://xxx.xxx.xxx.xxx"];
int imageCount = [self.xxxx.imageNum intValue];
for (int i=0; i<imageCount; i++) {
NSString *str1 = @"这里是拼图片请求url,根据实际需求";
self.imageURL = [url URLByAppendingPathComponent:str1];
[self displayImageByIndex:i ByImageURL:self.productImageURL];
}
}
-(void) displayImageByIndex:(NSInteger)index ByImageURL:(NSURL *)url
{
NSString *indexForString = [NSString stringWithFormat:@"%d",index];
if ([self.originalIndexArray containsObject:indexForString]) {
return;
}
UIImageView *imageView = [[UIImageView alloc] init];
imageView.tag = index;
ResourceContainer *imageOperation = [[ResourceContainer alloc] init];
imageOperation.resourceURL = url;
imageOperation.hostObject = self;
imageOperation.resourceDidReceive = @selector(imageDidReceive:);
imageOperation.imageView = imageView;
[imageView release];
[self.requsetImageQueue addOperation:imageOperation];
[self.originalOperationDic setObject:imageOperation forKey:indexForString];
[imageOperation release];
}
-(void)imageDidReceive:(UIImageView *)imageView {
if (imageView == nil||imageView.image == nil) { imageView.image = [UIImage imageNamed:@"no-pic-300-250.png"]; }
[self.openFlowView setImage:imageView.image forIndex:imageView.tag];
[self.originalIndexArray addObject:[NSString stringWithFormat:@"%d",imageView.tag]];
[self.originalOperationDic removeObjectForKey:[NSString stringWithFormat:@"%d",imageView.tag]]; } - (void)dealloc { [_requestImageQueue release];
[_originalIndexArray release];
[_originalOperationDic release];
[_imageURL release];
[super dealloc]; } @end
|
经过上述步骤,我们实现了加载网络图片时缓存功能,增强了用户体验效果。
参考:http://www.cnblogs.com/pengyingh/articles/2343061.html