iOS tableView中的MVC、MVVM

开头:最近在利用有道的api尝试做一个翻译的应用,其中用到了tableview。有一段时间没有接触这个常用UI,发现该忘的都忘了哈哈。

本文不着重讲述tableView的各种基本使用了,而打算通过下面几个方面来进行叙述思考。在复习tableView的同时,想思考一下代码的规范问题。

  • 1.tableView下中MVC思考
  • 2.tableView与自定义cell
  • 3.一个tableView,多种类型cell(MVVM模式)

1.tableView中MVC思考

先贴上一张MVC的一张大图(给自己看就好)

mvc.jpeg

controller 相当于媒介,帮助model和View建立其联系。道理我都懂,但是以往在coding的时候,往往会出现以下的情况(代码不看):


    -(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的设计思想。这可能会导致:

  • 1.将view(cell)和model(数据)在controller中建立起了直接的联系。
  • 2.又会让tableView显得庞然大物。

因此在这次coding 的过程中,我时不时有意地注意到了这个问题,将所有的与UI展示有关的数据交由View下来处理,而避免在controller中直接的设置。所以这次我的设置数据源的方法图片如下:

image

以往在设计一个tableView中有两种以上不同cell时候,我容易在cellForRowAtIndexPath:这个方法中作出许许多多的if-else的判断,而现在我将这个判断交由cell自己来做,controller自己不需要知道cell是要什么类型,而只要将得到的cell展示即可。

我们需要做的,就是传入需要的数据,可以indexPath也可以是model等。 这可能也很好的贯彻了“依赖注入”的设计原则。

同时,这可能对于后面的关于:自定义行高,一个tableView中有两个cell等提供有益的帮助。

不过白猫黑猫,能抓到老鼠的的都是好猫哈哈哈。

补充:注意一定要传入tableView,因为cell的复用问题。


2.tableView与自定义cell

这部分写给自己看哈哈哈,主要是遇到了几个忘记的知识点。

  • 1.如果事先给tableView注册了cell类型,则不需要进行cell为空的处理,缓存池中就会有足够的cell等待复用。
  • 2.在通过[_tableView registerClass...]注册了cell之后,在进行cell复用时,底层是调用了
    - (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier的方法,因此如果需要返回xib自定义的cell,则需要对这个方法override。
  • 3.在通过xib自定义时,需要通过tableViewDelegate设置行高(代理里的默认行高为44),否则可能无法完全展示xib的cell。
  • 4.通过xib加载cell时候,底层会调用awakeFromNib的方法(这个也忘了😂)

3.一个tableView,多种类型cell

在现如今的应用程序当中,一个tableView中含有多种类型的cell,这已是一个普遍的UI需求。

参考了网上各种方法之后,自我总结了一下。
我想到了如下两种:

  • 1.将相关参数传入view,通过view来返回需要指定类型的cell。
  • 2.根据两种不同的标识符,获取不同的cell。

对于第一种方法:

我在实现的过程中,将view与xib绑定在一起,根据传入的indexPath或者数据,返回出指定类型的的cell。以往我会在xib文件中只放一个cell,而此次我则不再是通过[array lastObject]取出唯一的cell,而是根据指定的index从多个cell中取出指定的cell。

image

附上伪码:

@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的Identifier:

同样是可以采用前面的方法来进行开发,但是细想一下,如果cell的类型过多,这样子会导致view中代码成本过高,相比与第一种方法,这种方法则更加麻烦。

如何解决?那就着手已产生的麻烦---胖View。

MVVM

开始写文章的时候并没有考虑,但是写着写着就觉得也许可以应用进来哈哈。9012希望能多写文章,记录笔记!

先贴几张MVVM的大图:

[图片上传失败...(image-bdeca-1549460154646)]

[图片上传失败...(image-36b52f-1549460154646)]


image

对于新面孔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,然而发现这里是一块肥肉,考虑篇幅,还得重新开一篇笔记细细评味😂。

参考

ReactiveCocoa and MVVM, an Introduction

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,711评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,932评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,770评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,799评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,697评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,069评论 1 276
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,535评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,200评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,353评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,290评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,331评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,020评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,610评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,694评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,927评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,330评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,904评论 2 341

推荐阅读更多精彩内容