版權聲明:本文爲博主原創文章,未經博主容許不得轉載。緩存
[objc] view plaincopy網絡
</pre><pre name="code" class="objc"> 異步
[objc] view plaincopy函數
</pre><pre name="code" class="objc"> url
[objc] view plaincopyspa
在前面的一篇博客中,我寫了一個瀑布流照片牆的程序,因爲以前的程序加載的圖片是本地的,因此在這篇文章中我來補上有關異步加載網絡圖片的代碼,來實現以前程序的效果,但願你們批評指正呀! .net
這個程序中大部分的代碼和以前的博客中貼出來的相同,不一樣的只是添加了圖片緩存機制,圖片異步下載線程函數,以及圖片點擊瀏覽的功能。線程
接下來看一下代碼實現部分:code
[objc] view plaincopyorm
#import "MyScrollView.h"
#define COORDINATE_X_LEFT 5
#define COORDINATE_X_MIDDLE MY_WIDTH/3 + 5
#define COORDINATE_X_RIGHT MY_WIDTH/3 * 2 + 5
#define PAGESIZE 21
@interface MyScrollView ()
@implementation MyScrollView
@synthesize isOnce = _isOnce;
@synthesize imagesName = _imagesName;
@synthesize loadedImageDic = _loadedImageDic;
@synthesize leftColumHeight = _leftColumHeight;
@synthesize midColumHeight = _midColumHeight;
@synthesize rightColumHeight = _rightColumHeight;
@synthesize loadedImageArray = _loadedImageArray;
@synthesize imgTag = _imgTag;
@synthesize imgTagDic = _imgTagDic;
@synthesize imageLoad = _imageLoad;
@synthesize page = _page;
@synthesize fileUtil = _fileUtil;
@synthesize imageCache = _imageCache;
@synthesize photoArray = _photoArray;
//@synthesize aDelegaet;
+ (MyScrollView *)shareInstance{
static MyScrollView *instance;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[self alloc] initWithFrame:CGRectMake(0, 0, MY_WIDTH, MY_HEIGHT)];
});
return instance;
}
/*
初始化scrollView的委託以及背景顏色,不顯示它的水平,垂直顯示條
*/
- (id)initWithFrame:(CGRect)frame{
self = [super initWithFrame:frame];
if(self){
self.delegate = self;
self.backgroundColor = [UIColor blackColor];
self.pagingEnabled = NO;
self.showsHorizontalScrollIndicator = NO;
self.showsVerticalScrollIndicator = NO;
self.isOnce = YES;
self.loadedImageDic = [[NSMutableDictionary alloc] init];
self.loadedImageArray = [[NSMutableArray alloc] init];
self.imgTagDic = [[NSMutableDictionary alloc] init];
self.photoArray = [[NSMutableArray alloc] init];
//初始化列的高度
self.leftColumHeight = 3.0f;
self.midColumHeight = 3.0f;
self.rightColumHeight = 3.0f;
self.imgTag = 10086;
self.page = 1;
self.fileUtil = [FileUtil shareInstance];
self.imageCache = [ImageCacher shareInstance];
_imageCache.myDelegate = self;
[self initWithPhotoBox];
}
return self;
}
/*
將scrollView界面分爲大小相等的3個部分,每一個部分爲一個UIView, 並設置每個UIView的tag
*/
- (void)initWithPhotoBox{
UIView *leftView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, MY_WIDTH/3, self.frame.size.height)];
UIView *middleView = [[UIView alloc] initWithFrame:CGRectMake(leftView.frame.origin.x + MY_WIDTH/3, 0, MY_WIDTH/3,
self.frame.size.height)];
UIView *rightView = [[UIView alloc] initWithFrame:CGRectMake(middleView.frame.origin.x + MY_WIDTH/3, 0, MY_WIDTH/3,
self.frame.size.height)];
//設置三個部分的tag
leftView.tag = 100;
middleView.tag = 101;
rightView.tag = 102;
//設置背景顏色
[leftView setBackgroundColor:[UIColor clearColor]];
[middleView setBackgroundColor:[UIColor clearColor]];
[rightView setBackgroundColor:[UIColor clearColor]];
[self addSubview:leftView];
[self addSubview:middleView];
[self addSubview:rightView];
self.imageLoad = [ImageLoader shareInstance];
[_imageLoad loadImage:nil];
//第一次加載圖片
for(int i = 0; i < PAGESIZE; i++){
NSString *imageName = [_imageLoad.imagesArray objectAtIndex:i];
[self imageStartLoading:imageName];
}
//當前爲第一頁
self.page = 1;
}
/*
* @brief 圖片加載通用函數
* @parma imageName 圖片名
*/
- (void)imageStartLoading:(NSString *)imageName{
NSURL *url = [NSURL URLWithString:imageName];
if([_fileUtil hasCachedImage:url]){
UIImageView *imageView = [[UIImageView alloc] init];
NSString *path = [_fileUtil pathForUrl:url];
imageView = [_imageLoad compressImage:MY_WIDTH/3 imageView:nil imageName:path flag:NO];
[self addImage:imageView name:path];
[self adjustContentSize:NO];
}else{
UIImageView *imageView = [[UIImageView alloc] init];
NSDictionary *dic = [NSDictionary dictionaryWithObjectsAndKeys:url, @"URL",
imageView, @"imageView", nil nil];
[NSThread detachNewThreadSelector:@selector(cacheImage:) toTarget:[ImageCacher shareInstance] withObject:dic];
}
}
/*
*調整scrollview
*/
- (void)adjustContentSize:(BOOL)isEnd{
UIView *leftView = [self viewWithTag:100];
UIView *middleView = [self viewWithTag:101];
UIView *rightView = [self viewWithTag:102];
if(_leftColumHeight >= _midColumHeight && _leftColumHeight >= _rightColumHeight){
self.contentSize = leftView.frame.size;
}else{
if(_midColumHeight >= _rightColumHeight){
self.contentSize = middleView.frame.size;
}else{
self.contentSize = rightView.frame.size;
}
}
}
/*
*獲得最短列的高度
*/
- (float)getTheShortColum{
if(_leftColumHeight <= _midColumHeight && _leftColumHeight <= _rightColumHeight){
return _leftColumHeight;
}else{
if(_midColumHeight <= _rightColumHeight){
return _midColumHeight;
}else{
return _rightColumHeight;
}
}
}
/*
*添加一張圖片
*規則:根據每一列的高度來決定,優先加載列高度最短的那列
*從新設置圖片的x,y座標
*imageView:圖片視圖
*imageName:圖片名
*/
- (void)addImage:(UIImageView *)imageView name:(NSString *)imageName{
//圖片是否加載
if([self.loadedImageDic objectForKey:imageName]){
return;
}
//若圖片還未加載則保存
[self.loadedImageDic setObject:imageView forKey:imageName];
[self.loadedImageArray addObject:imageView];
[_photoArray addObject:imageName];
[self imageTagWithAction:imageView name:imageName];
float width = imageView.frame.size.width;
float height = imageView.frame.size.height;
//判斷哪一列的高度最低
if(_leftColumHeight <= _midColumHeight && _leftColumHeight <= _rightColumHeight){
UIView *leftView = [self viewWithTag:100];
[leftView addSubview:imageView];
//從新設置座標
[imageView setFrame:CGRectMake(2, _leftColumHeight, width, height)];
_leftColumHeight = _leftColumHeight + height + 3;
[leftView setFrame:CGRectMake(0, 0, MY_WIDTH/3, _leftColumHeight)];
}else{
if(_midColumHeight <= _rightColumHeight){
UIView *middleView = [self viewWithTag:101];
[middleView addSubview:imageView];
[imageView setFrame:CGRectMake(2, _midColumHeight, width, height)];
_midColumHeight = _midColumHeight + height + 3;
[middleView setFrame:CGRectMake(MY_WIDTH/3, 0, MY_WIDTH/3, _midColumHeight)];
}else{
UIView *rightView = [self viewWithTag:102];
[rightView addSubview:imageView];
[imageView setFrame:CGRectMake(2, _rightColumHeight, width, height)];
_rightColumHeight = _rightColumHeight + height + 3;
[rightView setFrame:CGRectMake(22 * MY_WIDTH/3, 0, MY_WIDTH/3, _rightColumHeight)];
}
}
}
/*
將圖片tag保存,以及爲UIImageView添加事件響應
*/
- (void)imageTagWithAction:(UIImageView *)imageView name:(NSString *)imageName{
//將要顯示圖片的tag保存
imageView.tag = self.imgTag;
[self.imgTagDic setObject:imageName forKey:[NSString stringWithFormat:@"%ld", (long)imageView.tag]];
self.imgTag++;
//圖片添加事件響應
UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(imageClickWithTag:)];
tapRecognizer.delegate = self;
imageView.userInteractionEnabled = YES;
[imageView addGestureRecognizer:tapRecognizer];
[tapRecognizer release];
}
/*
//若三列中最短列距離底部高度超過30像素,則請求加載新的圖片
*/
- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
//可視檢查
//[self checkImageIsVisible];
if((self.contentOffset.y + self.frame.size.height) - [self getTheShortColum] > 30){
[self pullRefreshImages];
}
}
/*
上拉時加載新的圖片
*/
- (void)pullRefreshImages{
int index = self.page *PAGESIZE;
NSUInteger imgNum = [self.imageLoad.imagesArray count];
if(index >= imgNum){
//圖片加載完畢
[self adjustContentSize:YES];
}else{
if((imgNum - self.page*PAGESIZE) > PAGESIZE){
for (int i = index; i < PAGESIZE; i++) {
NSString *imageName = [_imageLoad.imagesArray objectAtIndex:i];
[self imageStartLoading:imageName];
}
}else{
for (int i = index; i < imgNum; i++) {
NSString *imageName = [_imageLoad.imagesArray objectAtIndex:i];
[self imageStartLoading:imageName];
}
}
self.page++;
}
}
/*
檢查圖片是否可見,若是不在可見視線內,則把圖片替換爲nil
*/
- (void)checkImageIsVisible{
for (int i = 0; i < [_loadedImageArray count]; i++) {
UIImageView *imgView = [_loadedImageArray objectAtIndex:i];
if((self.contentOffset.y - imgView.frame.origin.y) > imgView.frame.size.height ||
imgView.frame.origin.y > (self.frame.size.height + self.contentOffset.y)){
//不顯示圖片
imgView.image = nil;
}else{
//從新根據tag值顯示圖片
NSString *imageName = [self.imgTagDic objectForKey:[NSString stringWithFormat:@"%ld", (long)imgView.tag]];
if((NSNull *)imageName == [NSNull null]){
return;
}
UIImageView *view = [_imageLoad compressImage:MY_WIDTH/3 imageView:nil imageName:imageName flag:NO];
imgView.image = view.image;
}
}
}
//點擊圖片事件響應
- (void)imageClickWithTag:(UITapGestureRecognizer *)sender{
UIImageView *view = (UIImageView *)sender.view;
NSString *imageName = [self.imgTagDic objectForKey:[NSString stringWithFormat:@"%ld", (long)view.tag]];
PhotoViewController *photoView = [[PhotoViewController alloc] init];
photoView.imageArray = _photoArray;
photoView.imageName = imageName;
UIWindow *window = [[UIApplication sharedApplication].delegate window];
[window addSubview:photoView.view];
}
- (void)dealloc{
[_imagesName release];
[_imgTagDic release];
[_loadedImageArray release];
[_imageCache release];
[_fileUtil release];
[_imageLoad release];
[_photoArray release];
[super dealloc];
}
@end
當程序第一次加載或者下拉刷新時,就開始下載圖片,函數:imageStartLoading用於下載圖片,該函數爲每一次下載圖片都開啓一個線程,在ImageCacher類中有cacheImage函數,用於判斷該圖片是否已經存在本地,而且將圖片放入到視圖中去。
如下是ImageCacher類的代碼
[objc] view plaincopy
#import "ImageCacher.h"
@implementation ImageCacher
@synthesize fileUtil = _fileUtil;
@synthesize imageLoader = _imageLoader;
@synthesize myDelegate = _myDelegate;
+ (ImageCacher *)shareInstance{
static ImageCacher *instance;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[self alloc] init];
});
return instance;
}
- (id)init{
self = [super init];
if(self){
self.fileUtil = [FileUtil shareInstance];
self.imageLoader = [ImageLoader shareInstance];
}
return self;
}
- (void)cacheImage:(NSDictionary*)dic{
NSURL *url = [dic objectForKey:@"URL"];
NSFileManager *fileManage = [NSFileManager defaultManager];
NSData *data = [NSData dataWithContentsOfURL:url];
NSString *fileName = [_fileUtil pathForUrl:url];
if(data){
[fileManage createFileAtPath:fileName contents:data attributes:nil];
}
UIImageView *imageView = [dic objectForKey:@"imageView"];
imageView.image = [UIImage imageWithData:data];
imageView = [_imageLoader compressImage:MY_WIDTH/3 imageView:imageView imageName:nil flag:YES];
[self.myDelegate addImage:imageView name:fileName];
[self.myDelegate adjustContentSize:NO];
}
- (void)dealloc{
[super dealloc];
}
@end
因爲時間的關係,詳細的講解就留到下期來講吧!
[objc] view plaincopy
#import "ImageCacher.h"
@implementation ImageCacher
@synthesize fileUtil = _fileUtil;
@synthesize imageLoader = _imageLoader;
@synthesize myDelegate = _myDelegate;
+ (ImageCacher *)shareInstance{
static ImageCacher *instance;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[self alloc] init];
});
return instance;
}
- (id)init{
self = [super init];
if(self){
self.fileUtil = [FileUtil shareInstance];
self.imageLoader = [ImageLoader shareInstance];
}
return self;
}
- (void)cacheImage:(NSDictionary*)dic{
NSURL *url = [dic objectForKey:@"URL"];
NSFileManager *fileManage = [NSFileManager defaultManager];
NSData *data = [NSData dataWithContentsOfURL:url];
NSString *fileName = [_fileUtil pathForUrl:url];
if(data){
[fileManage createFileAtPath:fileName contents:data attributes:nil];
}
UIImageView *imageView = [dic objectForKey:@"imageView"];
imageView.image = [UIImage imageWithData:data];
imageView = [_imageLoader compressImage:MY_WIDTH/3 imageView:imageView imageName:nil flag:YES];
[self.myDelegate addImage:imageView name:fileName];
[self.myDelegate adjustContentSize:NO];
}
- (void)dealloc{
[super dealloc];
}
@end
因爲時間的關係,詳細的講解就留到下期來講吧!