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

版权声明:本文为博主原创文章,未经博主允许不得转载。

[objc] view plaincopy在CODE上查看代码片派生到我的代码片

  1. </pre><pre name="code" class="objc">  

[objc] view plaincopy在CODE上查看代码片派生到我的代码片

  1. </pre><pre name="code" class="objc">  

[objc] view plaincopy在CODE上查看代码片派生到我的代码片

  1. 在前面的一篇博客中,我写了一个瀑布流照片墙的程序,由于之前的程序加载的图片是本地的,所以在这篇文章中我来补上有关异步加载网络图片的代码,来实现之前程序的效果,希望大家批评指正呀!  

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

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


[objc] view plaincopy在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(0, 0, 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(0, 0, MY_WIDTH/3, self.frame.size.height)];  

  81.     UIView *middleView = [[UIView alloc] initWithFrame:CGRectMake(leftView.frame.origin.x + MY_WIDTH/3, 0, MY_WIDTH/3,  

  82.                                                                   self.frame.size.height)];  

  83.     UIView *rightView = [[UIView alloc] initWithFrame:CGRectMake(middleView.frame.origin.x + MY_WIDTH/3, 0, 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(0, 0, 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/3, 0, 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/3, 0, 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 plaincopy在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  


由于时间的关系,详细的讲解就留到下期来说吧!

[objc] view plaincopy在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  


由于时间的关系,详细的讲解就留到下期来说吧!


转载于:https://my.oschina.net/u/2559341/blog/597738

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值