IOS开发之异步加载网络图片并缓存本地实现瀑布流(一)

[objc]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. </pre><pre name="code" class="objc">  
[objc]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. </pre><pre name="code" class="objc">  
[objc]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. 在前面的一篇博客中,我写了一个瀑布流照片墙的程序,由于之前的程序加载的图片是本地的,所以在这篇文章中我来补上有关异步加载网络图片的代码,来实现之前程序的效果,希望大家批评指正呀!  

这个程序中大部分的代码和之前的博客中贴出来的相同,不同的只是添加了图片缓存机制,图片异步下载线程函数,以及图片点击浏览的功能。

接下来看一下代码实现部分:


[objc]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. #import "MyScrollView.h"  
  2.   
  3. #define COORDINATE_X_LEFT 5  
  4. #define COORDINATE_X_MIDDLE MY_WIDTH/3 + 5  
  5. #define COORDINATE_X_RIGHT MY_WIDTH/3 * 2 + 5  
  6. #define PAGESIZE 21  
  7.   
  8. @interface MyScrollView ()  
  9.   
  10. @end  
  11.   
  12. @implementation MyScrollView  
  13.   
  14. @synthesize isOnce = _isOnce;  
  15. @synthesize imagesName = _imagesName;  
  16. @synthesize loadedImageDic = _loadedImageDic;  
  17. @synthesize leftColumHeight = _leftColumHeight;  
  18. @synthesize midColumHeight = _midColumHeight;  
  19. @synthesize rightColumHeight = _rightColumHeight;  
  20. @synthesize loadedImageArray = _loadedImageArray;  
  21. @synthesize imgTag = _imgTag;  
  22. @synthesize imgTagDic = _imgTagDic;  
  23. @synthesize imageLoad = _imageLoad;  
  24. @synthesize page = _page;  
  25. @synthesize fileUtil = _fileUtil;  
  26. @synthesize imageCache = _imageCache;  
  27. @synthesize photoArray = _photoArray;  
  28. //@synthesize aDelegaet;  
  29.   
  30. + (MyScrollView *)shareInstance{  
  31.     static MyScrollView *instance;  
  32.     static dispatch_once_t onceToken;  
  33.     dispatch_once(&onceToken, ^{  
  34.         instance = [[self alloc] initWithFrame:CGRectMake(00, MY_WIDTH, MY_HEIGHT)];  
  35.         });  
  36.       
  37.     return instance;  
  38. }  
  39.   
  40. /* 
  41.  初始化scrollView的委托以及背景颜色,不显示它的水平,垂直显示条 
  42.  */  
  43. - (id)initWithFrame:(CGRect)frame{  
  44.     self = [super initWithFrame:frame];  
  45.     if(self){  
  46.         self.delegate = self;  
  47.         self.backgroundColor = [UIColor blackColor];  
  48.         self.pagingEnabled = NO;  
  49.         self.showsHorizontalScrollIndicator = NO;  
  50.         self.showsVerticalScrollIndicator = NO;  
  51.           
  52.         self.isOnce = YES;  
  53.         self.loadedImageDic = [[NSMutableDictionary alloc] init];  
  54.         self.loadedImageArray = [[NSMutableArray alloc] init];  
  55.         self.imgTagDic = [[NSMutableDictionary alloc] init];  
  56.         self.photoArray = [[NSMutableArray alloc] init];  
  57.   
  58.         //初始化列的高度  
  59.         self.leftColumHeight = 3.0f;  
  60.         self.midColumHeight = 3.0f;  
  61.         self.rightColumHeight = 3.0f;  
  62.         self.imgTag = 10086;  
  63.         self.page = 1;  
  64.           
  65.         self.fileUtil = [FileUtil shareInstance];  
  66.         self.imageCache = [ImageCacher shareInstance];  
  67.           
  68.         _imageCache.myDelegate = self;  
  69.           
  70.         [self initWithPhotoBox];  
  71.     }  
  72.       
  73.     return self;  
  74. }  
  75.   
  76. /* 
  77.  将scrollView界面分为大小相等的3个部分,每个部分为一个UIView, 并设置每一个UIView的tag 
  78.  */  
  79. - (void)initWithPhotoBox{  
  80.     UIView *leftView = [[UIView alloc] initWithFrame:CGRectMake(00, MY_WIDTH/3self.frame.size.height)];  
  81.     UIView *middleView = [[UIView alloc] initWithFrame:CGRectMake(leftView.frame.origin.x + MY_WIDTH/30, MY_WIDTH/3,  
  82.                                                                   self.frame.size.height)];  
  83.     UIView *rightView = [[UIView alloc] initWithFrame:CGRectMake(middleView.frame.origin.x + MY_WIDTH/30, MY_WIDTH/3,  
  84.                                                                  self.frame.size.height)];  
  85.     //设置三个部分的tag  
  86.     leftView.tag = 100;  
  87.     middleView.tag = 101;  
  88.     rightView.tag = 102;  
  89.       
  90.     //设置背景颜色  
  91.     [leftView setBackgroundColor:[UIColor clearColor]];  
  92.     [middleView setBackgroundColor:[UIColor clearColor]];  
  93.     [rightView setBackgroundColor:[UIColor clearColor]];  
  94.       
  95.     [self addSubview:leftView];  
  96.     [self addSubview:middleView];  
  97.     [self addSubview:rightView];  
  98.       
  99.     self.imageLoad = [ImageLoader shareInstance];  
  100.     [_imageLoad loadImage:nil];  
  101.       
  102.     //第一次加载图片  
  103.     for(int i = 0; i < PAGESIZE; i++){  
  104.         NSString *imageName = [_imageLoad.imagesArray objectAtIndex:i];  
  105.         [self imageStartLoading:imageName];  
  106.     }  
  107.       
  108.     //当前为第一页  
  109.     self.page = 1;  
  110. }  
  111.   
  112. /* 
  113.  * @brief 图片加载通用函数 
  114.  * @parma imageName 图片名 
  115.  */  
  116. - (void)imageStartLoading:(NSString *)imageName{  
  117.     NSURL *url = [NSURL URLWithString:imageName];  
  118.     if([_fileUtil hasCachedImage:url]){  
  119.         UIImageView *imageView = [[UIImageView alloc] init];  
  120.         NSString *path = [_fileUtil pathForUrl:url];  
  121.         imageView = [_imageLoad compressImage:MY_WIDTH/3 imageView:nil imageName:path flag:NO];  
  122.         [self addImage:imageView name:path];  
  123.         [self adjustContentSize:NO];  
  124.     }else{  
  125.         UIImageView *imageView = [[UIImageView alloc] init];  
  126.         NSDictionary *dic = [NSDictionary dictionaryWithObjectsAndKeys:url, @"URL",  
  127.                              imageView, @"imageView", nil nil];  
  128.         [NSThread detachNewThreadSelector:@selector(cacheImage:) toTarget:[ImageCacher shareInstance] withObject:dic];  
  129.     }  
  130. }  
  131.   
  132.   
  133. /* 
  134.  *调整scrollview 
  135.  */  
  136. - (void)adjustContentSize:(BOOL)isEnd{  
  137.     UIView *leftView = [self viewWithTag:100];  
  138.     UIView *middleView = [self viewWithTag:101];  
  139.     UIView *rightView = [self viewWithTag:102];  
  140.       
  141.     if(_leftColumHeight >= _midColumHeight && _leftColumHeight >= _rightColumHeight){  
  142.         self.contentSize = leftView.frame.size;  
  143.     }else{  
  144.         if(_midColumHeight >= _rightColumHeight){  
  145.             self.contentSize = middleView.frame.size;  
  146.         }else{  
  147.             self.contentSize = rightView.frame.size;  
  148.         }  
  149.     }  
  150. }  
  151.   
  152. /* 
  153.  *得到最短列的高度 
  154.  */  
  155. - (float)getTheShortColum{  
  156.     if(_leftColumHeight <= _midColumHeight && _leftColumHeight <= _rightColumHeight){  
  157.         return _leftColumHeight;  
  158.     }else{  
  159.         if(_midColumHeight <= _rightColumHeight){  
  160.             return _midColumHeight;  
  161.         }else{  
  162.             return _rightColumHeight;  
  163.         }  
  164.     }  
  165. }  
  166.   
  167. /* 
  168.  *添加一张图片 
  169.  *规则:根据每一列的高度来决定,优先加载列高度最短的那列 
  170.  *重新设置图片的x,y坐标 
  171.  *imageView:图片视图 
  172.  *imageName:图片名 
  173.  */  
  174. - (void)addImage:(UIImageView *)imageView name:(NSString *)imageName{  
  175.     //图片是否加载  
  176.     if([self.loadedImageDic objectForKey:imageName]){  
  177.         return;  
  178.     }  
  179.       
  180.     //若图片还未加载则保存  
  181.     [self.loadedImageDic setObject:imageView forKey:imageName];  
  182.     [self.loadedImageArray addObject:imageView];  
  183.     [_photoArray addObject:imageName];  
  184.       
  185.     [self imageTagWithAction:imageView name:imageName];  
  186.       
  187.     float width = imageView.frame.size.width;  
  188.     float height = imageView.frame.size.height;  
  189.       
  190.     //判断哪一列的高度最低  
  191.     if(_leftColumHeight <= _midColumHeight && _leftColumHeight <= _rightColumHeight){  
  192.         UIView *leftView = [self viewWithTag:100];  
  193.         [leftView addSubview:imageView];  
  194.         //重新设置坐标  
  195.         [imageView setFrame:CGRectMake(2, _leftColumHeight, width, height)];  
  196.         _leftColumHeight = _leftColumHeight + height + 3;  
  197.         [leftView setFrame:CGRectMake(00, MY_WIDTH/3, _leftColumHeight)];  
  198.     }else{  
  199.         if(_midColumHeight <= _rightColumHeight){  
  200.             UIView *middleView = [self viewWithTag:101];  
  201.             [middleView addSubview:imageView];  
  202.   
  203.             [imageView setFrame:CGRectMake(2, _midColumHeight, width, height)];  
  204.             _midColumHeight = _midColumHeight + height + 3;  
  205.             [middleView setFrame:CGRectMake(MY_WIDTH/30, MY_WIDTH/3, _midColumHeight)];  
  206.         }else{  
  207.             UIView *rightView = [self viewWithTag:102];  
  208.             [rightView addSubview:imageView];  
  209.   
  210.             [imageView setFrame:CGRectMake(2, _rightColumHeight, width, height)];  
  211.             _rightColumHeight = _rightColumHeight + height + 3;  
  212.             [rightView setFrame:CGRectMake(22 * MY_WIDTH/30, MY_WIDTH/3, _rightColumHeight)];  
  213.         }  
  214.     }  
  215. }  
  216.   
  217.   
  218. /* 
  219.  将图片tag保存,以及为UIImageView添加事件响应 
  220.  */  
  221. - (void)imageTagWithAction:(UIImageView *)imageView name:(NSString *)imageName{  
  222.     //将要显示图片的tag保存  
  223.     imageView.tag = self.imgTag;  
  224.     [self.imgTagDic setObject:imageName forKey:[NSString stringWithFormat:@"%ld", (long)imageView.tag]];  
  225.     self.imgTag++;  
  226.       
  227.     //图片添加事件响应  
  228.     UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(imageClickWithTag:)];  
  229.     tapRecognizer.delegate = self;  
  230.     imageView.userInteractionEnabled = YES;  
  231.     [imageView addGestureRecognizer:tapRecognizer];  
  232.     [tapRecognizer release];  
  233. }  
  234.   
  235.   
  236. /* 
  237.      //若三列中最短列距离底部高度超过30像素,则请求加载新的图片 
  238.  */  
  239. - (void)scrollViewDidScroll:(UIScrollView *)scrollView{  
  240.     //可视检查  
  241.     //[self checkImageIsVisible];  
  242.     if((self.contentOffset.y + self.frame.size.height) - [self getTheShortColum] > 30){  
  243.         [self pullRefreshImages];  
  244.     }  
  245. }  
  246.   
  247.   
  248. /* 
  249.  上拉时加载新的图片 
  250.  */  
  251. - (void)pullRefreshImages{  
  252.     int index = self.page *PAGESIZE;  
  253.     NSUInteger imgNum = [self.imageLoad.imagesArray count];  
  254.       
  255.     if(index >= imgNum){  
  256.         //图片加载完毕  
  257.         [self adjustContentSize:YES];  
  258.     }else{  
  259.         if((imgNum - self.page*PAGESIZE) > PAGESIZE){  
  260.             for (int i = index; i < PAGESIZE; i++) {  
  261.                 NSString *imageName = [_imageLoad.imagesArray objectAtIndex:i];  
  262.                 [self imageStartLoading:imageName];  
  263.             }  
  264.         }else{  
  265.             for (int i = index; i < imgNum; i++) {  
  266.                 NSString *imageName = [_imageLoad.imagesArray objectAtIndex:i];  
  267.                 [self imageStartLoading:imageName];  
  268.             }  
  269.         }  
  270.         self.page++;  
  271.     }  
  272. }  
  273.   
  274. /* 
  275.  检查图片是否可见,如果不在可见视线内,则把图片替换为nil 
  276.  */  
  277. - (void)checkImageIsVisible{  
  278.     for (int i = 0; i < [_loadedImageArray count]; i++) {  
  279.         UIImageView *imgView = [_loadedImageArray objectAtIndex:i];  
  280.           
  281.         if((self.contentOffset.y - imgView.frame.origin.y) > imgView.frame.size.height ||  
  282.            imgView.frame.origin.y > (self.frame.size.height + self.contentOffset.y)){  
  283.             //不显示图片  
  284.             imgView.image = nil;  
  285.         }else{  
  286.             //重新根据tag值显示图片  
  287.             NSString *imageName = [self.imgTagDic objectForKey:[NSString stringWithFormat:@"%ld", (long)imgView.tag]];  
  288.             if((NSNull *)imageName == [NSNull null]){  
  289.                 return;  
  290.             }  
  291.               
  292.             UIImageView *view = [_imageLoad compressImage:MY_WIDTH/3 imageView:nil imageName:imageName flag:NO];  
  293.             imgView.image = view.image;  
  294.         }  
  295.     }  
  296. }  
  297.   
  298. //点击图片事件响应  
  299. - (void)imageClickWithTag:(UITapGestureRecognizer *)sender{  
  300.     UIImageView *view = (UIImageView *)sender.view;  
  301.     NSString *imageName = [self.imgTagDic objectForKey:[NSString stringWithFormat:@"%ld", (long)view.tag]];  
  302.       
  303.     PhotoViewController *photoView = [[PhotoViewController alloc] init];  
  304.     photoView.imageArray = _photoArray;  
  305.     photoView.imageName = imageName;  
  306.     UIWindow *window = [[UIApplication sharedApplication].delegate window];  
  307.     [window addSubview:photoView.view];  
  308. }  
  309.   
  310.   
  311. - (void)dealloc{  
  312.     [_imagesName release];  
  313.     [_imgTagDic release];  
  314.     [_loadedImageArray release];  
  315.     [_imageCache release];  
  316.     [_fileUtil release];  
  317.     [_imageLoad release];  
  318.     [_photoArray release];  
  319.     [super dealloc];  
  320. }  
  321.   
  322. @end  
当程序第一次加载或者下拉刷新时,就开始下载图片,函数:imageStartLoading用于下载图片,该函数为每一次下载图片都开启一个线程,在ImageCacher类中有cacheImage函数,用于判断该图片是否已经存在本地,并且将图片放入到视图中去。

以下是ImageCacher类的代码

[objc]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. #import "ImageCacher.h"  
  2.   
  3. @implementation ImageCacher  
  4. @synthesize fileUtil = _fileUtil;  
  5. @synthesize imageLoader = _imageLoader;  
  6. @synthesize myDelegate = _myDelegate;  
  7.   
  8. + (ImageCacher *)shareInstance{  
  9.     static ImageCacher *instance;  
  10.     static dispatch_once_t onceToken;  
  11.     dispatch_once(&onceToken, ^{  
  12.         instance = [[self alloc] init];  
  13.     });  
  14.       
  15.     return instance;  
  16. }  
  17.   
  18. - (id)init{  
  19.     self = [super init];  
  20.     if(self){  
  21.         self.fileUtil = [FileUtil shareInstance];  
  22.         self.imageLoader = [ImageLoader shareInstance];  
  23.     }  
  24.     return self;  
  25. }  
  26.   
  27. - (void)cacheImage:(NSDictionary*)dic{  
  28.     NSURL *url = [dic objectForKey:@"URL"];  
  29.     NSFileManager *fileManage = [NSFileManager defaultManager];  
  30.     NSData *data = [NSData dataWithContentsOfURL:url];  
  31.       
  32.     NSString *fileName = [_fileUtil pathForUrl:url];  
  33.     if(data){  
  34.         [fileManage createFileAtPath:fileName contents:data attributes:nil];  
  35.     }  
  36.       
  37.     UIImageView *imageView = [dic objectForKey:@"imageView"];  
  38.     imageView.image = [UIImage imageWithData:data];  
  39.     imageView = [_imageLoader compressImage:MY_WIDTH/3 imageView:imageView imageName:nil flag:YES];  
  40.     [self.myDelegate addImage:imageView name:fileName];  
  41.     [self.myDelegate adjustContentSize:NO];  
  42. }  
  43.   
  44. - (void)dealloc{  
  45.     [super dealloc];  
  46. }  
  47.   
  48. @end  
  49. 由于时间的关系,详细的讲解就留到下期来说吧!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值