开头:最近在利用有道的api尝试作一个翻译的应用,其中用到了tableview。有一段时间没有接触这个经常使用UI,发现该忘的都忘了哈哈。react
先贴上一张MVC的一张大图(给本身看就好)api
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { TeacherHomeworkListCell *cell = [tableView dequeueReusableCellWithIdentifier:@"TeacherHomeworkListCell" forIndexPath:indexPath]; cell.delegate = self; NSArray *arr = homeworkListModelTDArray[indexPath.section]; cell.model = arr[indexPath.row]; if ([cell.model.requirements isEqualToString:@"0"]) { cell.operateView.hidden = YES; cell.correctHomeworkButton.hidden = YES; cell.operateViewNR.hidden = NO; } else { cell.operateView.hidden = NO; ....... 复制代码
贴上这么多之前的代码主要的,是能够看出在以往coding过程当中,我又容易忽视了mvc的设计思想。这可能会致使:缓存
所以在此次coding 的过程当中,我时不时有意地注意到了这个问题,将全部的与UI展现有关的数据交由View下来处理,而避免在controller中直接的设置。因此此次个人设置数据源的方法图片以下:bash
以往在设计一个tableView中有两种以上不一样cell时候,我容易在cellForRowAtIndexPath:这个方法中做出许许多多的if-else的判断,而如今我将这个判断交由cell本身来作,controller本身不须要知道cell是要什么类型,而只要将获得的cell展现便可。markdown
咱们须要作的,就是传入须要的数据,能够indexPath也能够是model等。 这可能也很好的贯彻了“依赖注入”的设计原则。mvc
同时,这可能对于后面的关于:自定义行高,一个tableView中有两个cell等提供有益的帮助。mvvm
不过白猫黑猫,能抓到老鼠的的都是好猫哈哈哈。ide
这部分写给本身看哈哈哈,主要是遇到了几个忘记的知识点。oop
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
的方法,所以若是须要返回xib自定义的cell,则须要对这个方法override。在现现在的应用程序当中,一个tableView中含有多种类型的cell,这已经是一个广泛的UI需求。ui
参考了网上各类方法以后,自我总结了一下。 我想到了以下两种:
我在实现的过程当中,将view与xib绑定在一块儿,根据传入的indexPath或者数据,返回出指定类型的的cell。以往我会在xib文件中只放一个cell,而这次我则再也不是经过[array lastObject]取出惟一的cell,而是根据指定的index从多个cell中取出指定的cell。
@implementation CustomCell - (instancetype)cellWithIndexPath:(NSIndexPath *)indexPath { CustomCell *cell = nil; NSArray *cellArr = [[NSBundle mainBundle] loadNibWith...]; if (...){ cell = [cellArr objectAtIndex:index]; }else if (...) { ... }else { cell = [cellArr lastObject]; } return cell; } @end 复制代码
可是这种方法的缺点也很明显,与tag的使用大同小异。当一个tableView须要许多种类型的cell来丰富内容的时候,采用这种方法在开发过程当中会带来必定的混乱。
能够适当的采用enum枚举,但同时也要注意xib中左面板中视图的上下位置。
例如上图中,NormalTyepCell 的index=1,MeTypeCell为2,而当二者调换了位置以后,索引也会发生改变。
我的也比较倾向于第二种方法,对于不一样的类型的cell,应有不一样的Identifier进行绑定,这样子比较科学哈哈,同时采用了较为高大上的MVVM,。
咱们大能够像第一种方式同样,从xib中取出所须要的cell,可是这也许就没有多个Identifier存在的必要性。而针对不一样标识符取出对应的cell,更多的是依赖:
[tableView dequeueReusableCellWithIdentifier:Identifier];
的调用。
一样是能够采用前面的方法来进行开发,可是细想一下,若是cell的类型过多,这样子会致使view中代码成本太高,相比与第一种方法,这种方法则更加麻烦。
如何解决?那就着手已产生的麻烦---胖View。
开始写文章的时候并无考虑,可是写着写着就以为也许能够应用进来哈哈。9012但愿能多写文章,记录笔记!
先贴几张MVVM的大图:
对于新面孔ViewModel:从MVC的controller中抽取出来的展现逻辑,负责从model中获取view所需的数据,转换成View能够展现的数据,并暴露公开的属性和命令供view进行绑定。
MVVM的采用能够很好的为view以及controller制定了瘦身的计划,咱们将“获取指定cell的Identifier”这一逻辑交由ViewModel来实现,而后经过controller告诉view须要哪一个cell。
附上viewModel和tableView设置数据源的伪码:
@implementation ViewModel - (NSString *)identifierWith:(Model *)model { if (model.type == ?){ return firstCellID; }else if (model ...){ return secondCellID; }else { return ... } } @end @implementation controller - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { NSString *identifier = [_viewModel identifierWith:model]; return [tableView dequeReusa....:identifier]; } @end 复制代码
在设置数据源方法中,我没有进行cell为空的操做处理,由于须要在这以前,对tableView进行全部类型cell的注册,我的也比较喜欢先注册cell的方式,这样子可让代码看起来更加直观。
结尾:
回顾前面所讲的,个人出发点能够理解为始终是一个---为controller制定瘦身计划,同时使代码更加容易维护。 以前只是一直想着coding,把功能实现就好,而历来没有想过将代码写在哪里会更加合理。 固然上面的方法并非最佳😂,自我总结,仅供参考,大神路过有意见,还望指点下。
原本还想经过尝试tableView自动算高来巩固复习tableView,然而发现这里是一块肥肉,考虑篇幅,还得从新开一篇笔记细细评味😂。