前言
一直以来我都不太习惯于UITableView的使用方式,因为只要是用tableview的控制器在调试代码的时候难免会来回翻看代码(代码不集中),而且有时候还要引入茫茫多的cell,并且还需要在代理方法中配置cell或者是在viewmodel里面配置cell。由于无法忍受这些不便,我决定另辟蹊径。
实现
这开始要做什么呢?既然是封装,那就先新建一个类来继承UITableView。然后我想让有关tableview相关代码集中,那么可以使用代码块来解决这个问题,在tableview初始化的时候代理就要指向自己,然后在代理方法中调用外界赋值的代码块来回调。
举个例子:
- (void)setCellResponseBlock:(SCTableViewCellResponseBlock)cellResponseBlock {
_cellResponseBlock = cellResponseBlock;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (_needDeselect) {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
if (_cellResponseBlock) {
_cellResponseBlock(_myDataSource[indexPath.section][indexPath.row], indexPath);
}
}
上面的问题告一段落。cell的注册怎么办呢?不引入文件就可以注册,这里我们需要感谢一下OC的runtime机制。
上代码:
Class cellClass = NSClassFromString(cellClassName);
if ([[NSBundle mainBundle] pathForResource:cellClassName ofType:@"nib"]) {
[self registerNib:[UINib nibWithNibName:cellClassName bundle:[NSBundle mainBundle]] forCellReuseIdentifier:cellClassName];
}
else {
[self registerClass:cellClass forCellReuseIdentifier:cellClassName];
}
问题处理到这儿,就剩下数据处理的问题了。这里我们还是用代码块回调吗?但是这么做不还是让控制器来解决cell的配置呀。或者说在这个封装的tableview中引入这些cell?那我把这个tableview抽出来用还要解决那一大堆cell的引入问题。这个时候category站出来了,我们需要在category里面编写一个协议来声明处理数据的接口,然后我们再将这个category引入到tableview中,创建的cell也要引入category并且实现协议。
category是酱紫的:
@protocol SCBaseTableCellInterFace <NSObject>
@required
//处理数据方法
- (void)dealWithData:(NSDictionary *)dict;
@optional
//返回cell高度方法。如果返回高度小于等于0或者不实现此方法,tableview将会按照自动布局方法计算行高。
- (CGFloat)getSubCellHeight;
@end
@interface UITableViewCell (BaseConfiguration)
@end
好了,设计的思路大概就是这样。不过这个封装也还存在很多不完善的地方,此文可供参考。代码传送门在这里。