iOS工作环境搭建iOS

以Manager组合实现tableView与VC解耦

2016-05-30  本文已影响573人  kirito_song

前言:笔者刚工作不久、而且是和一个即将离职的同事做工作交接。所以工作两个月以来基本都是在修前人的代码。然后、出现了这样一个问题。

屏幕快照 2016-05-30 下午1.14.42.png
没错、我们的页面有很多格式相似需要统一配置的列表、而截图只是其中一小部分。笔者一开始对结构项目不熟、UI也是刚来没多久。所以在UI提出新改动的时候、出现了很多次个别页面漏改的情况(footer底色啊、高度啊、下方分割线是否显示啊之类0.0)。需求改一点、就要把每个VC里的tb设置全部都改一遍实在是心累~

再然后、项目里的商品详情、也分出了三个模式


屏幕快照 2016-05-30 下午1.22.52.png

没错、每个模式列表的样式又有着些许的差别。于是乎项目里又出现了各种判断~


屏幕快照 2016-05-30 下午1.26.07.png

暂时这样写问题不大、但是想想、将来需求累加起来。单一模式的布局一改、就开始复杂了。

恰巧前阵子在看网络层架构、感受到了很多NetworkManager的好处。所以想试试能不能通过一个统一的列表管理器(ListManager)来统一调配项目中大部分风格一致的列表。于是、就有了以下的尝试。

——————————————正文——————————————————
以下、笔者只大概提出思路。毕竟对于菜鸡、言多必失。

1、ListManager

既然是Manager、必然要起到管理器的作用。

1.1 配置统一的tableView
要把尽量多的配置、交付给Manager、从而减轻了VC的压力。
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
//实现代理方法以代理方法为准
if ([self.delegate respondsToSelector:@selector(LMnumberOfSectionsInTableView:)]) {
return [self.delegate LMnumberOfSectionsInTableView:tableView];
}
//否则以默认为准
return Y;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
//可以根据VM配置、也可以手动配置
if ([self.delegate respondsToSelector:@selector(LMtableView:numberOfRowsInSection:)]) {
    return [self.delegate LMtableView:tableView numberOfRowsInSection:section];
  }
return X;
}

1.2 暴露代理API给VC、以备不时之需。上面的判断、就是那个意思。这样我们在控制器中实现之后、就可以覆盖manager中的原装设置

/* 暴露tableView代理方法至listManager所依赖控制器 */
- (NSInteger)LMnumberOfSectionsInTableView:(UITableView *)tableView;

- (CGFloat)LMtableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;

- (NSInteger)LMtableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;

- (UIView *)LMtableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section;

- (UIView *)LMtableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section;
。。。。。。。。

1.3 cell配置的实现
既然是统一配置、必然不可能把每个cell写进来所以、我们需要一个协议、用来约束cell。当然、下面的参数并不是充要条件、我只是copy了自己demo里的代码

@protocol BaseListManagerCellDelegate <NSObject>
@optional
 /**
 *  配置cell统一方法
 *  @param model     ListVM
 *  @param indexPath indexPath
 *  @param target    cell事件代理 将cell协议事件统一交由listmanager的代理实现
 *  如果cell需要代理回调事件、务必设置listmanager代理
 */

- (void)configurationCellWithModel:(BaseListModel*)model indexPath:(NSIndexPath *)indexPath target:(id)target;

于是乎、在所需cell遵循了协议之后、我们可以在ListManger中直接通过协议配置cell、如此这般
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
//Manager所属cell必须遵循协议。实现配置方法
//@"cellID"是我们在VC中需要做的、注册cell给manager
UITableViewCell<BaseListManagerCellDelegate> * cell = [tableView dequeueReusableCellWithIdentifier:@"cellID"];
// 通过协议方法配置cell
[cell configurationCellWithModel:model indexPath:indexPath target:self.delegate];
return cell;
}

2、ListModel

其实这个Model可有可无。如果你习惯FatModel或者MVVM。可以尝试添加进去如果公司的网络层统一度比较不错。简单页面用用、还是挺省事的

内部就不写了~毕竟每个公司网络架构都不同。心意到了就好。同样是copy的demo、不要太在意细节0.0

@interface BaseListModel : NSObject
@property (nonatomic) NSMutableArray *dataArray;
//关于数据源~我不是很喜欢里面放一个个model。不过放啥都无所谓了。不是重点呗~
@property (nonatomic) NSInteger page;
/* 请求url */
@property (nonatomic) NSString *dataUrl;
/* 删除url 不传入则不具备删除功能 */
@property (nonatomic) NSString *deleteDataUrl;
/* 删除的key 需要删除功能时必须传入*/
@property (nonatomic) NSString *deleteKey;
/**
 *  翻页
 */
- (void)next;

/**
 *  刷新
 */
- (void)freshenDataArray; 
/**
 *  删除
 *
 *  @param integer 数据位置
 */
- (void)deleteDataArrayAtIndex:(NSInteger)integer;

哦对~ListModel在实际的使用中、还可以暴露出几个API。毕竟很多时候在请求之后、页面还需要不同的提示啊、之类么0.0

@protocol KiritoListModelDelegate <NSObject>
@optional
/**
 *  刷新开始前代理
 *
 *  @return 继续执行model方法返回Yes 屏蔽返回No
 */
- (BOOL)modelBegainLoadDate;
- (void)modelEndLoadDate:(NSDictionary *)json;
/**
 *  删除开始前代理
 *
 *  @return 继续执行model方法返回Yes 屏蔽返回No
 */
- (BOOL)modelBegainDeleteDataAtIndex:(NSInteger)index;
- (void)modelEndDeleteData:(NSDictionary *)json;

想不起来还应该交待点什么、干脆再重申一次。FatModel并不是充要条件。

3、使用
我也不知道该说啥~反正感觉不太难0.0。贴一个项目里的使用吧


屏幕快照 2016-05-30 下午2.45.16.png

嗯、只需要配置一些充要条件。除非有什么特殊需求需要用API颠覆manger的配置。不然就不再用写啥了

4、总结

这并不是我造的轮子、充其量是一个思想而已。

我想解决的问题:(其实就是前言里写的状况~)
第一、既然网络层可以通过manager统一设置、为什么表现层的列表们不去交给相应的manager统一配置、每天搞很多重复工作真的很累。一旦UI有新Idea、真的很累、真的...
第二、一旦同一个页面有太多不同的模式。与其在cellForRow/height/footer/header里写很多判断。何不干脆单独写出三个manager。通过为VC装载不同的manager实现不同的页面配置。(对~这里就是组合

4、最后
第一次写博客、不知道有没有阐述明白。如果哪里不对、望轻拍。我会虚心接受的。
所以、还是贴demo吧~OC的Demo写的乱七八糟、而且没有注释。所以、Demo是Swift的、看看注释就好了。
下载链接

上一篇下一篇

猜你喜欢

热点阅读