一个简单登录示例的MVC和MVP实现

xbeB5.jpg

做者:长剑废水(博客) 登陆示例:MVC 自上篇《iOS基于MVC的项目重构》总结以后,我又思考了下面这个问题:在UIKit自身的设计中UIViewController是被当作C仍是V呢? 例如咱们点击View上某个Button时,可能会使用调用self.navigationController的pushViewController:animated:方法来跳转到一个新的界面。 在这个场景中,点击事件经过View传递到UIViewController,而后跳转到一个新的MVC。事件的逻辑处理是在UIViewController中完成的,事件的处理者是self(一个UIViewController),可见在UIKit中UIViewController是被视为Controller的。 那么第二个问题来了,若是须要在一个UIViewController中实现很复杂的View结构或者subViews之间的动画逻辑,那么如何合理设计UIViewController和UIView二者之间的关系呢? 在上文中说过,个人想法是经过给每个UIViewController设计一个对应的XXXContainerView,经过这样的方式来强行分离V和C,避免因为V太复杂时出现MassiveViewController。但这样同时也带来了一个坏处:没法像在UIViewController自带的view里添加控件同样,能够将控件的响应方法直接绑定到UIViewController的.m文件中,也没法享受相似viewDidDisappear:生命周期方法带来的便利了。 固然,对于有必定MVC经验的开发者,也能够经过相似下面的代码来简化XXXContainerView这一层: 1 2 3 [self.view addSubview:self.topView]; [self.view addSubview:self.midView]; [self.view addSubview:self.bottomView]; 虽然任何Demo都不可能模拟出实际项目中遇到的问题,但经过不一样横向对比仍是很容易看出不一样架构的区别所在。接下来,我将以我目前对MVC的理解,给出一个简单的登陆示例Demo(Demo地址)。 Demo十分简单,这里仅作简单说明: LoginContainerView:负责建立用户所能看到的界面,以及将向Controller中传递登陆事件和登陆参数。 LoginModel:提供接口完成具体的登陆业务,Demo中省略了网络层以及存储层。 LoginController:负责建立LoginContainerView,以及当监听到登陆事件时,调用LoginModel中的登陆业务方法。 因为仅为了明确MVC的结构,因此Demo中对不少实际项目设计到的业务没有具体处理,好比网络请求(Demo中经过本地进行了模拟),数据持久化,以及登陆成功后rootViewController的切换。 这里有一点值得谈论的时,对用户输入数据的校验应该放在哪一层来完成呢?为了简化调用,Demo中是直接放在View层来进行判断的。固然,好像放在任何一层都有道理。 上面也提到过,MVC的一个复杂点在于,当View结构复杂以后,若是一个UIViewcontroller来管理多个的复杂的View,势必会形成View层和Controller层的交互变得复杂,并随着业务增加逐渐膨胀,直至崩溃。 那么,为每一个单独的View构造一个对应的Controller是否可行呢? 其实UIKit就是这么作的,好比UINavigationController栈中的每一项,都是一个新的MVC,更具体的关于多重MVC的介绍能够参见斯坦福大学公开课:iOS 8开发-多重 MVC。 可是实际开发中对于咱们自定义的继承自UIView的类,好像咱们都并无对其建立一个Controller的习惯—除非你愿意加班来完成这些额外的代码。苹果也没有强制推荐这么作—不然,只要设置不能单首创建UIView,只有经过UIViewController才能建立UIView就能够了。 接下来,一样对这个登陆示例,我会再给出一个MVP的例子。经过两者横向对比,二者的差别会很明显的体现出来。 登陆示例:MVP 在上文MVC登陆示例中提到了一点,在一个Controller管理多个复杂View的场景时,C和V之间的事件以及参数传递会变得很不畅,而实际开发中咱们也没有为每一个继承自View建立对应Controller的开发习惯。 为何会出现这么别扭的状况呢?《iOS基于MVC的项目重构》总结中我简单提到过MVC和MVP的差别: 个人理解是,MVP是用户视角:所见即View。MVC则是程序员视角:I control everyone。 在群里讨论的时候有人问我这句话如何解释,在这里我详细说明一下。 MVC中的C能够比喻为一个大管家,家里的每一个成员(View)须要就餐时,会将每一个人的口味偏好告知给管家(Controller),管家将这些信息告知厨房(Model),厨房作好后上菜开饭。 MVP中的P则能够比喻为一个私人秘书,你要吃什么直接跟秘书(Presenter)说就行了,只要秘书(Presenter)拥有调用厨房(Model)的权限便可。 一句话总结,C是家族大管家,P是贴身小秘书。 可能这里解释的仍是不太清楚,仍是直接用代码来讲明吧。 MVP登陆示例Demo Demo的简单说明以下: View层:LoginViewController负责建立UI,响应交互。当有交互事件触发时,调用本身的preseter的对应方法处理。 Presenter层:LoginPresenter,是LoginViewController的贴身秘书,负责具体处理事件交互,并将处理结果报告给LoginViewController。 Model层:LoginModel,完成登陆业务逻辑。 对比MVC,之前View的事件通知给Controller可能须要使用block,delegate,View结构层级复杂的话可能还须要使用通知等等。还会多个View共用一个Controller的状况:Controller拿到Model的返回后,须要将返回值交给View并逐级传递下去完成展现。 而在MVP中,每一个View都会有一个贴身Presenter来处理交互,这样就将本来MVC中的多View共用Controller的场景进行了拆分,这样避免了出现跨层传值的状况。(示例涉及到一个界面,由于没有模拟这种状况) 架构设计并非为了给开发者增长麻烦,而是在开发及维护的大层面上给开发者减小麻烦。 可能有的开发者会说,这么简单的一个登录随便写写不就完了,所谓”专家”就会把简单问题复杂化。可是,若是每一个人都随便写写的话, “There are a thousand Hamlets in a thousand people’s eyes.” 莎士比亚的这句话在程序开发中绝对是禁忌,没有人愿意维护一段代码的时候还要穿越时空去复现你开发时的思惟。程序员

相关文章
相关标签/搜索