引言
MVC架构模式,把系统划分为Model - View - Controller 三个基本的部分。其中model(模型层)负责对数据进行封装与存储;view(视图层)负责对数据进行展示以及监听用户的交互;controller(控制器)作为view与model的桥梁,负责view与model间的数据传递,同时处理数据传递过程中的业务逻辑,以及响应view层接收到的用户交互。
下面放上网上经典的交互图:

MVC存在的问题
iOS中,model层和view层之间是禁止通讯的,必须有controller层来协调view和model之间的变化。根据职责划分:
model:封装并存储数据
view:数据展示、监听用户交互
controller:协调view和model,处理协调过程中涉及的业务逻辑,响应view监听的交互
分析可知,controller承载了太多的内容,在加上iOS中并未将controller单独分离出来,其自身还要维护一个view,势必会导致controller如同一个巨无霸,动则上千行代码,即便能通过代码归类以及详细注释增加可读性,面对如此大的代码量、如此复杂的业务内容,也会让人倍感头疼。
Controller瘦身之充实Model
提出疑惑:model只是一个纯粹的数据结构吗?
我在过往的开发中,在对json->Object的数据转模型过程中,经历过 获取到数据后为对象属性逐个赋值、为对象添加接收json数据返回对象的类方法、使用Mantle进行映射和使用ObjectMapper进行映射等过程。其中只有作为开发的初始阶段,数据转模型是放在model之外的。这样做,会让model显的比较单薄,而数据转模型代码如果在多个地方都存在,会产生很多垃圾代码。将数据转模型这一逻辑转移到model层后,model相对而言就不会那么单薄了,同时也大大增强了数据->模型的复用性,外部只需要调用接口即可完成。
当然,如果基于对controller的瘦身,还可以将数据向展示出输出的业务转移到model层。比如,我们有一个Persion类,有Int类型的age属性,UI层做显示的时候,不能直接显示Int数据,所以势必会将其转化为String类型。这时候就可以在model层添加一个将age转成字符串的接口,外部需要时直接调用即可。
controller瘦身之分离代理
iOS开发中,UITableView是出现频率较高的控件之一。使用UITableView就很难避免使用其UITableViewDataSource以及UITableViewDelegate这两个协议。往往在这两个协议的方法实现中,代码会占用controller代码的很大篇幅。如果将这两个协议的实现从controller中分离出去,让一个第三者类来实现,一些交互信息通过第三者类的代理或者通过通过block的形式实现,当然这会使架构看起来不那么“MVC”,但是对于controller的瘦身,还是很有帮助的。而且,让controller这位“大佬”多了一个“小弟”,听上去也不那么糟糕(手动滑稽~)
controller瘦身之分离控件的初始化
lazy var buyBtn:UIButton= { let btn =UIButton() btn.backgroundColor = UIColor.clear btn.addTarget(self, action: #selector(buyBtnAction), for: UIControlEvents.touchUpInside) btn.setTitle(kText("买入"), for: UIControlState.normal) btn.setTitleColor(UIColor.init(hex:0x109053), for: .normal) btn.titleLabel?.font=UIFont(name:"PingFang SC", size:16) return btn }()
以上是对买入按钮通过懒加载的方式进行的初始化,在UIViewController中,这种组件的初始化比比皆是,即便使用Mark进行了分段,但其庞大的代码量依然是让人头疼的问题。我通常的做法是,为一些组件添加一些通用的便利构造函数,controller需要创建组件时,通过调用便利构造函数,传入一些配置相关的参数,即可得到想要的组件对象,这样代码不仅可读性更强,开发者只需要查看构造函数的实现,即可通过参数判断出组件的构造过程以及构造出怎样的组件对象,同时也更加简洁。当然,这样的局限性同样不小,特别是对于大型的团队协作开发,组件的扩展管理同样会带来很多问题。因此,这种方法需要慎用。
controller瘦身之动画实现向view迁移
@implementation ViewController: UIViewController //弹窗动画效果 - (void)animatedAlertView { AlertView *alert = [[AlertView alloc] initWithMessage: @"这是一条弹窗警告信息"]; alert.alpha = 0; alert.center = self.view.center; alert.transform = CGAffineTransformMakeScale(0.01, 0.01); [UIView animateWithDuration: 0.25 animations: ^{ alert.alpha = 1; alert.transform = CGAffineTransformIdentity; }]; } @end
在以往的开发中,经常会看到这种代码,甚至同种动画效果在不同地方多次出现。动画的实现迁移到view层,我的理由有两个:
1、动画实现与演示建立了依存关系:谁的动画谁实现
2、可以增强动画的复用
总结
本篇文章,做为我在开发过程中,对MVC的理解,和使用上的一些体会,分享给大家。MVC作为经典的架构模式,受到苹果官方所推崇,虽然有其局限性,但是我们如果灵活应用,同样可以得到很好的效果。我们在实际开发过程中,也不必纠结于什么架构模式是最好的,因为没有一种架构能够做到绝对的完美。多学、多看,在学习的过程中,找到适合自己的架构模式。它并不是也不会是一种结果,因为我们面对的需求本身就是动态的,它是一个过程,伴随着我们不断成长于进步,也为我们的开发生活带来许多刺激与惊喜。
网友评论