IOS開發網絡加載圖片緩存策略之──ASIDownloadCache緩存策略

 在我們實際工程中,很多情況需要從網絡上加載圖片,然後將圖片在imageview中顯示出來,但每次都要從網絡上請求,會嚴重影響用戶體驗,爲了不是每次顯示都需要從網上下載數據,希望將圖片放到本地緩存,因此我們需要一個好的的緩存策略,今天我將我在項目工程中的實際經驗分享給大家,我這裏主要介紹一下強大的ASIHTTPRequest的緩存策略,以及使用方法:

 

    下面是具體步驟:

    一、設置緩存策略

    首先在SplitDemoAppDelegate委託代理中,實現如下代碼:

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

 

#import <UIKit/UIKit.h>

 

 

@class ASIDownloadCache;


 

 

@interface SplitDemoAppDelegate : NSObject <UIApplicationDelegate,UITabBarControllerDelegate> {

    UIWindow *_window;

    ASIDownloadCache *_downloadCache;            //下載緩存策略

}

 

 

@property (nonatomic, retain) ASIDownloadCache *downloadCache;

@end
     
    在SplitDemoAppDelegate.m文件中,代碼如下:

#import "SplitDemoAppDelegate.h"

@implementation SplitDemoAppDelegate

@synthesize window=_window;

@synthesize downloadCache = _downloadCache;

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions

{

 

    //初始化ASIDownloadCache緩存對象

   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];

    // Override point for customization after application launch.

    [self.window makeKeyAndVisible];

    return YES;

}

 

 

- (void)dealloc

{

    [_window release];

    [_downloadCache release];

   [super dealloc];

}

 

 

@end 

 

    二、創建緩存線程

    這一步是創建一個NSOperation類,實現緩存的方法,代碼如下:

    ResourceContainer.h文件實現:

 

 

#import <Foundation/Foundation.h>

#import "ASIHTTPRequest.h"

#import "SplitDemoAppDelegate.h"

 

@interface ResourceContainer : NSOperation {

NSURL *_resourceURL;            //資源請求url

NSObject *_hostObject;             

SEL _resourceDidReceive;      //資源接手響應方法  

SplitDemoAppDelegate *_appDelegate;            //應用委託對象

ASIHTTPRequest *_httpRequest;            

UIImageView *_imageView;              

}

 

@property (nonatomic, retain) NSURL *resourceURL;

@property (nonatomic, retain) NSObject *hostObject;

@property (nonatomic, assign) SEL resourceDidReceive;

@property (nonatomic, assign) SplitDemoAppDelegate   *appDelegate;

@property (nonatomic, retain) ASIHTTPRequest *httpRequest;

@property (nonatomic, retain) UIImageView *imageView;

 

//http請求回調方法

-(void)didStartHttpRequest:(ASIHTTPRequest *)request;

-(void)didFinishHttpRequest:(ASIHTTPRequest *)request;

-(void)didFailedHttpRequest:(ASIHTTPRequest *)request;

 

//取消資源請求

-(void)cancelReourceGet;

//資源接收回調方法

-(void)resourceDidReceive:(NSData *)resource;

 

@end

 

 

    ResourceContainer.m文件實現:

 

 

#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聲明文件中,

 

#import <UIKit/UIKit.h>

@interface DetailViewController :UIViewController {

 

    NSURL                          *_imageURL;                    //圖片url

    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實現文件中,

 

 

#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"];

 

    //這個是從器返回有圖片數目,self.xxxx根據具體的場合

    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對象

    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是我用的coverFlow,coverFlow的使用方法網上很多,自己找吧

    [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

 

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

上一篇:IOS開發UI展示之UIScrollView ──原理下一篇:IOS開發網絡篇之──ASIHTTPRequest詳解
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章