Skip to content

A simple table view implementation, aimed at explaining how table view works

Notifications You must be signed in to change notification settings

bravegogo/SMTableView

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

10 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

SMTableView

A simple table view implementation, aimed at explaining how table view works
本文讲述了一个 table view 的简单实现, 意在解释 table view 是如何工作的

原理概述

SMTableView 继承自 UIScrollView, 直接利用了ScrollView 滑动的特性, 使得代码省去了滑动处理这一块的逻辑。想了解更多ScrollView的原理,请参考 http://oleb.net/blog/2014/04/understanding-uiscrollview/
SMTableView逻辑大概可以分为这几块:计算cell位置、 对cell进行布局、cell的重用、ScrollView滑动的处理

  • 计算cell位置
    根据delegate获取到cell的数量和每个的高度,加起来得到总高度,然后设置ScrollView的contentSize, 就确定了scrollView的滚动区域
_numberOfCells = [_tableViewDelegate numberOfRowsInTableView:self];
_cellYOffsets = [NSMutableArray new];
_cellHeights = [NSMutableArray new];

float height = 0;
for (int i = 0  ; i < _numberOfCells; i ++) {
    float cellHeight = [_tableViewDelegate heightForRow:i inTableView:self];
    [_cellHeights addObject:@(cellHeight)];
    height += cellHeight;
    [_cellYOffsets addObject:@(height)];
}
CGSize size = CGSizeMake(CGRectGetWidth(self.frame), height);

[self setContentSize:size];
  • 对cell进行布局
    首先获取到显示区域,然后获取到显示区域的cell,并设置相应的frame
_displayRange = [self displayRange];
for (int i = (int)_displayRange.location ; i < _displayRange.length + _displayRange.location; i ++) {
    SMTableViewCell* cell = [self _cellForRow:i];
    [self addSubview:cell];
    _visibleCellsMap[@(i)] = cell;
    cell.frame = [self _rectForCellAtRow:i];
}
  • cell的重用
    对cell布局完成后,这个时候是回收不可见cell的较好时机,获取不可见cell,并将其从visibleCells中移除,加入到cellCache中
NSDictionary* dic = [_visibleCellsMap copy];
NSArray* keys = dic.allKeys;
for (NSNumber* rowIndex  in keys) {
    int row = [rowIndex intValue];
    if (! NSLocationInRange(row, range)) {
        SMTableViewCell* cell = _visibleCellsMap[rowIndex];
        [_visibleCellsMap removeObjectForKey:rowIndex];
        [_cacheCells addObject:cell];
        [cell removeFromSuperview];
    }
}
  • ScrollView滑动的处理
    当ScrollView滑动的时候,检测displayRange是否发生变化,如果发生变化重新进行布局和回收cell等工作
NSRange range = [self displayRange];
if (! NSEqualRanges(_displayRange, range)) {
    [self layoutNeedDisplayCells];
}

如何使用

SMTableView定义如下

@interface SMTableView : UIScrollView

@property (nonatomic, strong) id<SMTableViewDelegate> tableViewDelegate;

//获取可重用的Cell
- (SMTableViewCell *) dequeueTableViewCellForIdentifier:(NSString*)identifier;

//刷新tableView
- (void) reloadData;
@end

SMTableViewDelegate定义如下

@protocol SMTableViewDelegate <NSObject>
- (NSInteger) numberOfRowsInTableView:(SMTableView *)tableView;                          //获取行数
- (CGFloat) heightForRow:(NSInteger)row inTableView:(SMTableView *)tableView;            //获取每行行高
- (SMTableViewCell *) cellForRow:(NSInteger)row inTableView:(SMTableView *)tableView;    //获取每行的cell
@end

例子

- (void)testTableView
{
    SMTableView *tableView = [[SMTableView alloc] initWithFrame:self.view.bounds];
    __weak ViewController *wself = self;
    tableView.tableViewDelegate = wself;
    [self.view addSubview:tableView];
    [tableView reloadData];
}

- (NSInteger)numberOfRowsInTableView:(SMTableView *)tableView
{
    return 1000;
}

- (CGFloat)heightForRow:(NSInteger)row inTableView:(SMTableView *)tableView
{ 
    return 100;
}

- (SMTableViewCell *)cellForRow:(NSInteger)row inTableView:(SMTableView *)tableView
{
	SMTableViewCell *cell = [tableView dequeueTableViewCellForIdentifier:@"SMTableViewCell"];
    if (!cell) {
        cell = [[SMTableViewCell alloc] initWithIdentifier:@"SMTableViewCell"];
        UILabel *label = [[UILabel alloc] initWithFrame:cell.bounds];
        label.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
        [cell addSubview:label];
    }
    
    UILabel *label = cell.subviews.firstObject;
    label.text = [NSString stringWithFormat:@"我是第%@", @(row)];
    cell.backgroundColor = [self randomColor];
    return cell;
}

参考

本文参考了 DZTableView( https://github.com/yishuiliunian/DZTableView ) 的实现,并对其进行了精简和改进。

About

A simple table view implementation, aimed at explaining how table view works

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Objective-C 100.0%