UITableView这个玩意儿是经常要用到的,初始化,设置delegate,设置dataSource,然后实现代理方法,数据源方法,然后VC的代码就多了一大堆,是不是感觉好臃肿,看着就不舒服呢?那么就对他进行一下简单的瘦身吧!
抽出一个类,叫cellDataAdapter,这个类用处很大,是关联Controller和Model以及View的,相当于一个转换器一样。
// // RDCellDataAdapter.h // UITableViewAnimation // // Created by 键盘上的舞者 on 16/10/23. // Copyright © 2016年 键盘上的舞者. All rights reserved. // #import <Foundation/Foundation.h> #import <UIKit/UIKit.h> @interface RDCellDataAdapter : NSObject /** * 重用标识符 */ @property (nonatomic, copy) NSString *cellReuseIdentifier; /** * 数据 */ @property (nonatomic, strong) id data; /** * cell的高度 */ @property (nonatomic, assign) CGFloat cellHeight; /** * cell的类型 */ @property (nonatomic, assign) NSInteger cellType; /** * 便捷构造方法 * * @param reuseIdentifier 重用标识符 * @param data 数据 * @param cellHeight 高度 * @param cellType 类型 * * @return cellDataAdapter */ + (RDCellDataAdapter *)cellDataAdapterWithReuseIdentifier:(NSString *)reuseIdentifier data:(id)data cellHeight:(CGFloat)cellHeight cellType:(NSInteger)cellType; @end
// // RDCellDataAdapter.m // UITableViewAnimation // // Created by 键盘上的舞者 on 16/10/23. // Copyright © 2016年 键盘上的舞者. All rights reserved. // #import "RDCellDataAdapter.h" @implementation RDCellDataAdapter + (RDCellDataAdapter *)cellDataAdapterWithReuseIdentifier:(NSString *)reuseIdentifier data:(id)data cellHeight:(CGFloat)cellHeight cellType:(NSInteger)cellType { RDCellDataAdapter *adapter = [[[self class] alloc] init]; adapter.cellReuseIdentifier = reuseIdentifier; adapter.data = data; adapter.cellHeight = cellHeight; adapter.cellType = cellType; return adapter; } @end
再抽出一个类CustomCell,继承自UITableViewCell.
// // RDCustomCell.h // UITableViewAnimation // // Created by 键盘上的舞者 on 16/10/23. // Copyright © 2016年 键盘上的舞者. All rights reserved. // #import <UIKit/UIKit.h> #import "RDCellDataAdapter.h" @class RDCustomCell; @protocol RDCustomCellDelegate <NSObject> @optional - (void)customCell:(RDCustomCell *)customCell event:(id)event; @end @interface RDCustomCell : UITableViewCell /** * 代理 */ @property (nonatomic, weak) id<RDCustomCellDelegate> delegate; /** * cellDataAdapter */ @property (nonatomic, weak) RDCellDataAdapter *cellDataAdapter; /** * data */ @property (nonatomic, weak) id data; /** * indexPath */ @property (nonatomic, weak) NSIndexPath *indexPath; /** * tableview */ @property (nonatomic, weak) UITableView *tableView; /** * 是否显示 */ @property (nonatomic, assign) BOOL display; /** * cell配置 */ - (void)setupCell; /** * 构建UI */ - (void)buildSubView; /** * cell读取数据 */ - (void)loadContent; /** * 便捷方法构造cellDataAdapter * * @param identifier 重用标识符 * @param data data * @param cellHeight cellHeight * @param cellType cellType * * @return cellDataAdapater */ + (RDCellDataAdapter *)cellDataAdapterWithReuseIdentifier:(NSString *)identifier data:(id)data cellHeight:(CGFloat)cellHeight cellType:(NSInteger)cellType; /** * 将cellDataAdapter若引用到cell * * @param cellDataAdapter cellDataAdapter * @param data data * @param indexPath indexPath * @param tableView 指向的tableView */ - (void)setWeakReferenceWithCellDataAdapter:(RDCellDataAdapter *)cellDataAdapter data:(id)data indexPath:(NSIndexPath *)indexPath tableView:(UITableView *)tableView; /** * 更新cell高度 * * @param newHeight 新高度 * @param animated 是否开启动画 */ - (void)updateCellHeightWithNewHeight:(CGFloat)newHeight animated:(BOOL)animated; /** * 点击事件 */ - (void)selectedEvent; /** * 通过数据计算cell的高度 */ + (CGFloat)heightWithData:(id)data; @end
// // RDCustomCell.m // UITableViewAnimation // // Created by 键盘上的舞者 on 16/10/23. // Copyright © 2016年 键盘上的舞者. All rights reserved. // #import "RDCustomCell.h" @implementation RDCustomCell - (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) { [self setupCell]; [self buildSubView]; } return self; } #pragma mark - 由子类重写 - (void)setupCell { } - (void)buildSubView { } - (void)loadContent { } - (void)selectedEvent { } #pragma mark - method + (RDCellDataAdapter *)cellDataAdapterWithReuseIdentifier:(NSString *)identifier data:(id)data cellHeight:(CGFloat)cellHeight cellType:(NSInteger)cellType { NSString *tmpIdentifier = identifier.length <= 0 ? NSStringFromClass([self class]) : identifier; return [RDCellDataAdapter cellDataAdapterWithReuseIdentifier:tmpIdentifier data:data cellHeight:cellHeight cellType:cellType]; } + (CGFloat)heightWithData:(id)data { return 0.f; } - (void)setWeakReferenceWithCellDataAdapter:(RDCellDataAdapter *)cellDataAdapter data:(id)data indexPath:(NSIndexPath *)indexPath tableView:(UITableView *)tableView { _cellDataAdapter = cellDataAdapter; _data = data; _indexPath = indexPath; _tableView = tableView; } - (void)updateCellHeightWithNewHeight:(CGFloat)newHeight animated:(BOOL)animated { if (_tableView && _cellDataAdapter) { if (animated) { _cellDataAdapter.cellHeight = newHeight; [_tableView beginUpdates]; [_tableView endUpdates]; } else { _cellDataAdapter.cellHeight = newHeight; [_tableView reloadData]; } } } @end
根据自己的项目去增加或者删减。
给UITableView增加一个category
// // UITableView+CellClass.h // UITableViewAnimation // // Created by 键盘上的舞者 on 16/10/23. // Copyright © 2016年 键盘上的舞者. All rights reserved. // #import <UIKit/UIKit.h> @class RDCustomCell; @class RDCellDataAdapter; @interface CellClassType : NSObject @property (nonatomic, copy) NSString *classString; @property (nonatomic, copy) NSString *reuseIdentifier; + (instancetype)cellClassTypeWithClassString:(NSString *)classString reuseIdentifier:(NSString *)reuseIdentifier; @end NS_INLINE CellClassType *cellClass(NSString *classString, NSString *reuseIdentifier) { return [CellClassType cellClassTypeWithClassString:classString reuseIdentifier:reuseIdentifier.length <= 0 ? classString : reuseIdentifier]; } @interface UITableView (CellClass) - (void)registerCellClass:(NSArray <CellClassType *> *)cellClass; - (RDCustomCell *)dequeueAndLoadContentFromCellDataAdapter:(RDCellDataAdapter *)cellDataAdapter indexPath:(NSIndexPath *)indexPath; @end
// // UITableView+CellClass.m // UITableViewAnimation // // Created by 键盘上的舞者 on 16/10/23. // Copyright © 2016年 键盘上的舞者. All rights reserved. // #import "UITableView+CellClass.h" #import "RDCellDataAdapter.h" #import "RDCustomCell.h" @implementation CellClassType + (instancetype)cellClassTypeWithClassString:(NSString *)classString reuseIdentifier:(NSString *)reuseIdentifier { CellClassType *classType = [[[self class] alloc] init]; classType.classString = classString; classType.reuseIdentifier = reuseIdentifier; return classType; } @end @implementation UITableView (CellClass) - (void)registerCellClass:(NSArray<CellClassType *> *)cellClass { for (int i = 0; i < cellClass.count; i++) { CellClassType *type = cellClass[i]; [self registerClass:NSClassFromString(type.classString) forCellReuseIdentifier:type.reuseIdentifier]; } } - (RDCustomCell *)dequeueAndLoadContentFromCellDataAdapter:(RDCellDataAdapter *)cellDataAdapter indexPath:(NSIndexPath *)indexPath { RDCustomCell *cell = [self dequeueReusableCellWithIdentifier:cellDataAdapter.cellReuseIdentifier forIndexPath:indexPath]; [cell setWeakReferenceWithCellDataAdapter:cellDataAdapter data:cellDataAdapter.data indexPath:indexPath tableView:self]; [cell loadContent]; return cell; } @end
分离出来之后,你可以这样去使用它。
1.初始化UITableView
self.tableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain]; self.tableView.delegate = self; self.tableView.dataSource = self; self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone; //注册 [self.tableView registerCellClass:@[cellClass(@"TableViewCellTapAnimationCell", nil)]]; [self.view addSubview:self.tableView];
使用UITableView的category中的便捷方法,注册cell
2.设置数据源
NSArray *tmp = @[[TapAnimationModel modelWithName:@"test1" selected:NO], [TapAnimationModel modelWithName:@"test2" selected:NO], [TapAnimationModel modelWithName:@"test3" selected:NO]]; self.dataArray = [NSMutableArray array]; for (int i = 0; i < tmp.count; i++) { [self.dataArray addObject:[TableViewCellTapAnimationCell cellDataAdapterWithReuseIdentifier:nil data:tmp[i] cellHeight:80 cellType:0]]; }
TapAnimationModel为你的数据模型。
然后向dataArray中添加dataAdapter,data就是TapAnimationModel。
3.设置delegate和dataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return self.dataArray.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { TableViewCellTapAnimationCell *cell = (TableViewCellTapAnimationCell *)[tableView dequeueAndLoadContentFromCellDataAdapter:self.dataArray[indexPath.row] indexPath:indexPath]; return cell; } - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { RDCellDataAdapter *adapter = self.dataArray[indexPath.row]; return adapter.cellHeight; }
tableView dequeueAndLoadContentFromCellDataAdapter:<#(RDCellDataAdapter *)#> indexPath:<#(NSIndexPath *)#>
这句代码就是来进行cell复用的,具体实现如下。
- (RDCustomCell *)dequeueAndLoadContentFromCellDataAdapter:(RDCellDataAdapter *)cellDataAdapter indexPath:(NSIndexPath *)indexPath { RDCustomCell *cell = [self dequeueReusableCellWithIdentifier:cellDataAdapter.cellReuseIdentifier forIndexPath:indexPath]; [cell setWeakReferenceWithCellDataAdapter:cellDataAdapter data:cellDataAdapter.data indexPath:indexPath tableView:self]; [cell loadContent]; return cell; }
在自定义的cell中读取数据。
- (void)loadContent { TapAnimationModel *model = self.cellDataAdapter.data; _name.text = model.name; }
现在,你在你的controller中使用UITableView,就不需要再像以前那样去写那么大一堆代码,你只需要在VC中设置好你的数据源,向UITableView中注册你自定义的cell,然后在你的自定义cell(继承自CustomCell)中去布局UI,去设置相关的数值就搞定了。