之前面试的时候会有很多人问道 UITableviewCellde 重用机制, 大部分回答都是
在缓存池初中通过 dequeueReusableCellWithIdentifier:CellIdentifier 方法取出可重用的 cell, 在一个 cell 离开屏幕显示的范围内, 会自动被加入到缓存池中,然后在缓存池中取出一个 cell, 放到当前屏幕上;用重用机制会节省性能,避免出现一些因为网络因素而造成的卡顿现象。
复用机制避免了大量的初始化过程, 我们可以节约很大一部分资源; 下面我们来试着模仿 tableview 创建一个复用视图吧~
实例化一个重用池;
新建一个继承自NSObject 的类, reusePool; 在reusePool 中定义三个方法,
在类的.m文件中, 实现刚才定义的几个方法, 并定义两个属性, wattingQueue 和 usingQueue, 作为存放视图的容器; 实现刚才定义的几个方法
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 
 | - (instancetype)init{
 self = [super init];
 if (self) {
 _waitingQueue  = [NSMutableSet set];
 _useingQueue   = [NSMutableSet set];
 }
 return self;
 }
 // 如果存在, 从等待队列中移除一个, 在使用中的队列增加一个
 -(UIView *)getReuseTableView{
 UIView *view = [_waitingQueue anyObject];
 if (view == nil) {
 return nil;
 }else{
 [_waitingQueue removeObject:view];
 [_useingQueue addObject:view];
 return view;
 }
 }
 //添加可重用视图到重用池
 -(void)addViewForReusePool:(UIView *)view{
 if (view == nil) {
 return;
 }
 [_useingQueue addObject:view];
 }
 //重置重用池
 -(void)reset{
 UIView *view = nil;
 while ((view = [_useingQueue anyObject]) ) {
 [_useingQueue removeObject:view];
 [_waitingQueue addObject:view];
 }
 }
 
 | 
实现视图
定义一个继承自UITableView 的视图类, reuseTableView; 给 reuseTableView 设置一个代理方法, 来获取需要用到的数据;
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 
 | #import <UIKit/UIKit.h>@protocol QKReuseTableViewDataSource <NSObject>
 /**
 获取字母索引条
 @param tableview tableview
 @return 结果数组
 */
 -(NSArray <NSString*> *)indexTitleFromReuseTable:(UITableView *)tableview;
 @end
 @interface QKReuseTableView : UITableView
 @property (nonatomic,weak) id   <QKReuseTableViewDataSource> indexDataSource;
 @end
 
 | 
在. m 文件中定义两个属性
| 12
 3
 4
 5
 6
 
 | @interface QKReuseTableView (){
 UIView *containerView;
 QKReusePool *reusePool;
 }
 @end
 
 | 
重写 tableview 的reloadData 方法
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 
 | -(void)reloadData{[super reloadData];
 if (containerView == nil) {
 containerView = [[UIView alloc] init];
 containerView.backgroundColor = UIColor.whiteColor;
 [self.superview insertSubview:containerView aboveSubview:self];
 }
 if (reusePool == nil) {
 reusePool = [[QKReusePool alloc] init];
 }
 //初始化的时候重置重用池
 [reusePool reset];
 //    reload 索引条
 [self reloadIndexTitle];
 }
 -(void)reloadIndexTitle{
 //    设置一个title数组
 NSArray <NSString *> * titleArray  = nil;
 if ([self.indexDataSource respondsToSelector:@selector(indexTitleFromReuseTable:)]) {
 titleArray = [self.indexDataSource indexTitleFromReuseTable:self];
 }
 if (!titleArray  titleArray.count<=0) {
 [containerView setHidden:YES];
 return;
 }
 NSUInteger count = titleArray.count;
 CGFloat btnWidth = 60;
 CGFloat btnHeight = self.frame.size.height/count;
 for (int i = 0; i< count; i++) {
 NSString *title = [titleArray objectAtIndex:i];
 UIButton *btn = (UIButton *)[reusePool getReuseTableView];
 if (btn == nil) {
 btn = [[UIButton alloc] initWithFrame:CGRectZero];
 btn.backgroundColor = UIColor.whiteColor;
 [reusePool addViewForReusePool:btn];
 NSLog(@"creat  a  btn");
 }else{
 NSLog(@"reuse button");
 }
 [containerView addSubview:btn];
 [btn setTitle:title forState:UIControlStateNormal];
 [btn  setTitleColor:UIColor.blackColor forState:UIControlStateNormal];
 [btn setFrame:CGRectMake(0, i*btnHeight, btnWidth, btnHeight)];
 }
 [containerView setHidden:NO];
 containerView.frame = CGRectMake(self.frame.origin.x + self.frame.size.width - btnWidth, self.frame.origin.y, btnWidth, self.frame.size.height);
 }
 
 | 
代码在reuseCell 文件夹 git仓库链接地址