iOS页面框架

由于业务特殊大部分业务需求都是配置累页面同一个页面cell种类特别多所以同事封装了一套框架来简化开发,学习了一下,然后自己总结改动了一个简化版,改动了sectioncellModel以及headerView的实现方式

github地址


正常我们在开发中用tableView时,每一个vc都会有一个tableView且都需要实现dataSource、delegate

正常数据到显示要通过以下方式传递:

  1. 数据传递到vc(或者直接在vc请求)
  2. vc实现tableViewdelegate
  3. cellForRowAtIndexPath方法找出对应data传递到cell
  4. cell填充数据展示
  5. 一般我们cell会持有data

然而如果cell样式过多:

1
[{"type":"1","value":[...]},{"type":"2","value":""},{"type":"3","value":""}]

然而如果data结构和cell样式都过多:

1
2
3
[group1, 数据结构1]
[group2,数据结构2]
[group3,数据结构3]

问题:

  1. 每一个vc都实现tableView代理的代码重复
  2. 界面cell样式和数据结构多的时候会导致cellForRowAtIndexPath里很多胶水代码
  3. cell持有model,不同业务模块的相同样式cell会出现业务model依赖

解决方案:

  1. 提供manager类来管理代理HHTableViewManager,所有vc只需要创建一个manager对象
1
2
3
4
5
6
- (HHTableViewManager *)manager {
if (!_manager) {
_manager = [[HHTableViewManager alloc] initWithTableView:self.tableView];
}
return _manager;
}
  1. 为每一个cell提供与之对应的cellModel就相当于vcviewModel
  • cellModelcell 绑定(HHCellViewModelProxy),同时暴露cell可操作的属性及交互给调用方,cell实现协议(HHCellViewProxy),来实现数据传递
1
2
3
4
5
6
7
8
9
10
11
12
@protocol HHCellViewModelProxy <NSObject>
@required
/**
返回当前viewModel 对应的类名
@return string
*/
- (NSString *)bindClassString;
@end
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@protocol HHCellViewProxy <NSObject>
/**
cell 初始化
*/
- (void)cellForInitalized;
/**
cell 填充数据
@param 对应的ViewModel Cell 可以持有ViewModel
*/
- (void)configCellWithViewModel:(id <HHCellViewModelProxy>)viewModel;
/**
cell 高度
@param viewModel
@return 高度
*/
+ (CGFloat)heightForCellWithViewModel:(id <HHCellViewModelProxy>)viewModel;
@end
  1. 提供section来管理cellModel(HHSectionProxy)的增删(可以把它当成一个Array
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@protocol HHSectionProxy <NSObject>
@required
@property (nonatomic, strong, readonly)NSArray<HHCellViewModelProxy> *rows;
@property (nonatomic, strong)id<HHSectionViewModelProxy> bindHeaderViewModel;
@property (nonatomic, strong)id<HHSectionViewModelProxy> bindFootererViewModel;
- (void)addRow:(id<HHCellViewModelProxy>)row;
- (void)addRows:(NSArray<HHCellViewModelProxy> *)rows;
- (void)insertRow:(id<HHCellViewModelProxy>)row atIndex:(NSUInteger)index;
- (void)insertRow:(id<HHCellViewModelProxy>)row beforeRow:(id<HHCellViewModelProxy>)baseRow;
- (void)insertRow:(id<HHCellViewModelProxy>)row behindRow:(id<HHCellViewModelProxy>)baseRow;
- (void)removeRow:(id<HHCellViewModelProxy>)row;
- (void)removeRows:(NSArray<HHCellViewModelProxy> *)rows;
- (void)removeRowAtIndex:(NSUInteger)index;
- (void)removeAllRows;
@end

  1. manager管理section的增删

最终:manager会在cellForRow里找到section找到cellModell找到cell

1
2
3
4
5
6
7
8
9
10
11
12
13
14
- (nonnull UITableViewCell *)tableView:(nonnull UITableView *)tableView cellForRowAtIndexPath:(nonnull NSIndexPath *)indexPath {
Class cellClass = [self getCurrentRowViewClassWithIndexPath:indexPath];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:NSStringFromClass(cellClass)];
if (!cell) {
cell = [[cellClass alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:NSStringFromClass(cellClass)];
if ([cell respondsToSelector:@selector(cellForInitalized)]) {
[cell performSelector:@selector(cellForInitalized)];
}
}
if ([cell respondsToSelector:@selector(configCellWithViewModel:)]) {
[(id <HHCellViewProxy>)cell configCellWithViewModel:[self rowAtIndexPath:indexPath]];
}
return cell;
}

最后我们创建页面的代码

1
2
3
4
5
6
7
8
9
10
11
12
HHBaseSection *section = [[HHBaseSection alloc] init];
for (NSDictionary *dic in array) {
HHListViewModel *viewModel = [[HHListViewModel alloc] init];
viewModel.title = dic[@"title"];
viewModel.detail = dic[@"detail"];
viewModel.height = [dic[@"height"] floatValue];
[section addRow:viewModel];
}
[self.manager addSection:section];
[self.manager reloadData];

cellcellModel是不依赖业务的,我们可以把他们放在统一的一个组件库里