iOS 如何实现View的复用(以访问相册为例)
来源:互联网 发布:网站seo综合查询 编辑:程序博客网 时间:2024/05/23 01:21
原创Blog,转载请注明出处
http://blog.csdn.net/hello_hwc?viewmode=list
欢迎关注我的iOS SDK详解专栏
http://blog.csdn.net/column/details/huangwenchen-ios-sdk.html
前言:Tableview可以加载很多数据,但是却不会引起内存问题,因为在加载Cell的时候,我们使用了这个方法 dequeueReusableCell......
,这个方法就是使用了Cell的复用。同理,如果我们要实现自己的View加载很多东西的时候,View复用也是十分必要的,例如用ScrollView加载很多东西,如果不断的创建新的View,毫无疑问最后内存会不够用。
如何实现View复用?
我自己有三条规则
- 建立两个NSSet,一个代表复用池,一个代表可视池。
- 每当需要新的View时候,先检查复用池里有没有,如果有,则取出,没有则创建新的。
- 监听用户可视范围,需要新的View则按照2中的规则来得到一个新的View,如果一个View不可见了,则放到复用池里
一个简单的例子-访问相册
效果
先实现规则1
为了实现规则1,需要声明两个NSSet,当然我们也需要一个Scrollview和一个数据源
@property (strong,nonatomic)UIScrollView * containScrollView;@property (strong,nonatomic)NSMutableArray * assetsArray;@property (strong,nonatomic)NSMutableSet * dequePool;//复用池@property (strong,nonatomic)NSMutableSet * visiablePool;//可见池
并且对其初始化
-(void)commonInit{ self.dequePool = [[NSMutableSet alloc] init]; self.visiablePool = [[NSMutableSet alloc] init]; _containScrollView = [[UIScrollView alloc] initWithFrame:CGRectIntegral([UIScreen mainScreen].bounds)]; _containScrollView.delegate = self; _containScrollView.backgroundColor = [UIColor blackColor]; _containScrollView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; _containScrollView.pagingEnabled = true; _containScrollView.showsHorizontalScrollIndicator = false; _containScrollView.showsVerticalScrollIndicator = false; self.automaticallyAdjustsScrollViewInsets = NO; [self.view addSubview:_containScrollView];}-(void)awakeFromNib{ [self commonInit];}
然后实现规则2
因为要复用,所以要一个复用的类似UITableviewCell之类的View,这里我们继承UIImageView,实现一个带index和可以加载相册图片的ImageView
这个类的头文件
@class PHAsset;@interface LeoImageView : UIImageView@property (nonatomic,copy)NSNumber * index;@property (nonatomic,copy)PHAsset * asset;-(void)loadImage;@end
然后,写一个方法来实现规则2
-(LeoImageView *)generageDequeImageview{ LeoImageView * imageview = [self.dequePool anyObject]; if (imageview == nil) { imageview = [[LeoImageView alloc] initWithFrame:_containScrollView.bounds]; imageview.contentMode = UIViewContentModeScaleAspectFit; }else{ [self.dequePool removeObject:imageview]; } return imageview;}
实现规则3
这里监听ScrollViewDidScroll
-(void)scrollViewDidScroll:(UIScrollView *)scrollView{ CGFloat scrollViewWidth = CGRectGetWidth(scrollView.frame); CGFloat scrollViewHeight = CGRectGetHeight(scrollView.frame); CGFloat startOrigin = scrollView.bounds.origin.x; CGFloat endOrigin = scrollView.bounds.origin.x + scrollViewWidth; //可视区域的开始 NSInteger startVisiableIndex = (NSInteger)floor(startOrigin/scrollViewWidth); startVisiableIndex = [self IntegerShouldNotBeyoundBounds:startVisiableIndex]; //可视区域结束 NSInteger endVisiableIndex = (NSInteger)floor(endOrigin/scrollViewWidth); endVisiableIndex = [self IntegerShouldNotBeyoundBounds:endVisiableIndex]; NSMutableSet * curVisiableSet = [[_visiablePool valueForKeyPath:@"index"] mutableCopy]; NSMutableSet * needVisiableSet = [self createSetWith:startVisiableIndex End:endVisiableIndex]; if ([curVisiableSet isEqualToSet:needVisiableSet] == false) { if (curVisiableSet.count > needVisiableSet.count) { //View可以被复用 [curVisiableSet minusSet:needVisiableSet]; for (LeoImageView * imageView in [_visiablePool copy]) { if ([curVisiableSet containsObject:imageView.index]) { [imageView removeFromSuperview]; imageView.image = nil; imageView.index = nil; [_visiablePool removeObject:imageView]; [_dequePool addObject:imageView]; } } }else{ //需要新的View [needVisiableSet minusSet:curVisiableSet]; for (NSNumber * index in needVisiableSet) { LeoImageView * imageView = [self generageDequeImageview]; imageView.asset = [self.assetsArray objectAtIndex:index.integerValue]; [imageView loadImage]; imageView.index = index; imageView.frame = CGRectMake(index.integerValue * scrollViewWidth, 0, scrollViewWidth,scrollViewHeight); [_containScrollView addSubview:imageView]; [_visiablePool addObject:imageView]; } } }}
这里有两个辅助方法
-(NSInteger)IntegerShouldNotBeyoundBounds:(NSInteger)number{ if (number < 0) { number = 0; } if (number > self.assetsArray.count - 1) { number = self.assetsArray.count - 1; } return number;}-(NSMutableSet *)createSetWith:(NSInteger)start End:(NSInteger)end{ NSMutableSet * set = [NSMutableSet new]; for (NSInteger index = start;index <= end;index++) { [set addObject:@(index)]; } return set;}
然后,我们的复用架构就完成了。其他的代码就是访问图片了,注意Photo.h要求系统>8.0
完整工程可以在这里下载
http://download.csdn.net/detail/hello_hwc/9123757
0 0
- iOS 如何实现View的复用(以访问相册为例)
- iOS 如何实现View的复用(以访问相册为例)
- iOS访问相册以及拍照保存至相册的实现
- iOS uitableview自定义相册(实现拍照并保存在指定目录以相册的形式展示图片)
- iOS访问相册及拍照保存的实现实例
- 【Android学习】自定义View的实现----以圆形图片控件为例
- 以CentOS为例总结如何配置SSH安全访问
- 如何写windbg高级脚本---以访问文件的windbg脚本为例说明
- 如何写windbg高级脚本---以访问文件的windbg脚本为例说明
- 如何写windbg高级脚本---以访问文件的windbg脚本为例说明
- iOS相册访问 ALAssetsLibrary(获取到相册的图片)+ 图片格式
- SSH实现无密码访问--以centOS为例
- iOS访问手机自带的相册
- 自定义view的基本思路与步骤(以radioButton为例)
- 如何使用Sublime的插件(以HexViewer为例)
- 如何实现自定义的数据结构?以线性表的实现为例分析
- iOS 访问相机 相册
- iOS 访问相机、相册
- go json
- java SE复习笔记35
- Javascript模块化编程(三):require.js的用法
- 下一代SOA:服务技术与面向服务简明指南——互动出版网
- js之DOM操作(访问兄弟节点)
- iOS 如何实现View的复用(以访问相册为例)
- 黑马程序员——设计模式——装饰、单例、模版方法
- 自定义 android 标题栏
- 如何使用eclipse构建SVN上面的maven项目
- 关于android 百度地图离线包的调用问题
- 为什么给css添加border和padding不起效果
- Hihocoder 1228 Mission Impossible 6
- Git版本控制及repo工具简介
- Socket模型详解(转),有完成端口链接