iOS 如何实现View的复用(以访问相册为例)
2015-09-21 13:41
465 查看
原创Blog,转载请注明出处
http://blog.csdn.net/hello_hwc?viewmode=list
欢迎关注我的iOS SDK详解专栏
http://blog.csdn.net/column/details/huangwenchen-ios-sdk.html
前言:Tableview可以加载很多数据,但是却不会引起内存问题,因为在加载Cell的时候,我们使用了这个方法
建立两个NSSet,一个代表复用池,一个代表可视池。
每当需要新的View时候,先检查复用池里有没有,如果有,则取出,没有则创建新的。
监听用户可视范围,需要新的View则按照2中的规则来得到一个新的View,如果一个View不可见了,则放到复用池里
一个简单的例子-访问相册
效果
先实现规则1
为了实现规则1,需要声明两个NSSet,当然我们也需要一个Scrollview和一个数据源
并且对其初始化
然后实现规则2
因为要复用,所以要一个复用的类似UITableviewCell之类的View,这里我们继承UIImageView,实现一个带index和可以加载相册图片的ImageView
这个类的头文件
然后,写一个方法来实现规则2
实现规则3
这里监听ScrollViewDidScroll
这里有两个辅助方法
然后,我们的复用架构就完成了。其他的代码就是访问图片了,注意Photo.h要求系统>8.0
完整工程可以在这里下载
http://download.csdn.net/detail/hello_hwc/9123757
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,需要声明两个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
相关文章推荐
- ios NSDictionary\NSMutableDictionary
- iOS 日期格式 星期几 本地
- iOS集成支付宝
- iOSCoreAnimation动画系列教程(一):CABasicAnimation【包会】
- Thinkpad X240修改bios引导方式
- iOS集成支付宝
- Mac iOS推送测试
- iOS应用开发之地图位置解析
- iOS 字典是否相等
- iOS9适配
- 64位IOS系统中敲壳提取32位程序
- xamarin ios KeyBoardHide
- ios 将矩形图片裁剪成圆形图片
- 整理iOS9适配中出现的坑(图文)
- iOS项目更新之升级Xcode7 & iOS9
- 正则表达式在iOS中的运用
- iOS cocoapods安装
- iOS中Bitcode的报错
- iOS 9部分问题
- <二>Copy和mutableCopy——iOS开发的疑惑