文档章节

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

Align
 Align
发布于 2016/01/05 14:54
字数 1607
阅读 107
收藏 0

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

[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(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 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  


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


© 著作权归作者所有

Align
粉丝 11
博文 65
码字总数 71695
作品 0
昌平
高级程序员
私信 提问
iOS开发swift版异步加载网络图片(带缓存和缺省图片)

iOS开发之swift版异步加载网络图片 与SDWebImage异步加载网络图片的功能相似,只是代码比较简单,功能没有SD的完善与强大,支持缺省添加图片,支持本地缓存。 异步加载图片的核心代码如下: ...

珲少
2015/06/25
0
2
iOS运营级B2B服务平台App、自定义图标库、个人中心页面、识别身份证Demo、瀑布流等源码

iOS精选源码 简单的个人中心页面-自定义导航栏并予以渐变动画(http://www.code4app.com/thread-10860-1-1.html) 一个近乎完整的可识别中国身份证信息的Demo 可自动快速...(http://www.code4a...

Android爱开源
2018/10/25
0
0
Java转iOS-第一个项目总结(1)

0.前言 本人14年12月份,从网站开发组转到了移动开发组,自己的java两年半工作经验变成了objective-c零经验。2015年1月份新启动了一个移动项目,年后因为人事变动,自己从辅助开发变成了"核心...

蛙牛
2015/03/31
0
67
(转)直接拿来用!最火的iOS开源项目(二)

“每一次的改变总意味着新的开始。”这句话用在iOS上可谓是再合适不过的了。GitHub上的iOS开源项目数不胜数,iOS每一次的改变,总会引发iOS开源项目的演变,从iOS 1.x到如今的iOS 7,有的项目...

孙启超
2013/06/21
0
1
OSChina 技术专题之 Swift 苹果全新开发语言

Swift 是苹果新推出的编程语言,专门针对 OS X 和 iOS 的应用开发。Swift 在各个方面优于 Objective-C,也不会有那么多复杂的符号和表达式。同时,Swift 更加快速、便利、高效、安全。除此之...

OSC编辑部
2014/11/10
4.2K
4

没有更多内容

加载失败,请刷新页面

加载更多

揭秘阿里云背后神秘而富有能量的一群人

作为某创业公司CTO兼CTO兼CFO,带领众子弟行走于云端计算,累计犒赏已达757157.09银两,江湖人称紫龙,就是众多阿里云大使中低调内敛的一位。其话不多,一个典型的技术男,但又热心钻研传播推...

阿里云云栖社区
14分钟前
0
0
深入浅出Mybatis系列(一)---Mybatis源码分析环境准备

Mybatis源码分析环境准备 源码下载地址: https://blog.mybatis.org/p/products.html 把下载好多源码导入idea 之后可以在Test包下进行源码分析 这里我们就把源码分析的环境准备好了,下一篇文...

须臾之余
31分钟前
0
0
使用JDK的观察者接口进行消息推送

观察者模式就是对对象内部的变化进行观察,当发生改变时做出相应的响应。代码样例见 设计模式整理 ! 因为观察者模式较为重要,使用频率较高,JDK早已经提供了内置的观察者接口以及被观察者父...

算法之名
39分钟前
10
0
supervisor的配置与laravel php artisan queue:work的配置

安装环境 centos 7.2 安装supervisor easy_install supervisor echo_supervisord_conf > /etc/supervisord.conf 配置supervisor 如下 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20......

bengozhong
44分钟前
1
0
DevExpress Winforms Controls:安装使用系统要求文档

【DevExpress WinForms v19.1下载】 本文档包含了有关安装和使用DevExpress WinForms控件的系统要求信息。 .NET Framework 下图展示了支持的.NET Framework版本。 Microsoft已发布.NET Fram...

FILA6666
56分钟前
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部