武汉北大青鸟中南软件学院
400-027-0822

MVC:登录示例

2016-06-23供稿中心: 北大青鸟武汉中南软件学院

UIKit自身的设计中UIViewController是被当做C还是V呢?

例如我们点击View上某个Button时,可能会使用调用self.navigationController的pushViewController: animated:方法来跳转到一个新的界面.

在这个场景中,点击事件通过View传递到UIViewController,然后跳转到一个新的MVC.事件的逻辑处理是在UIViewController中完成的,事件的处理者是self(一个UIViewController),可见在UIKit中UIViewController是被视为Controller的.

那么第二个问题来了,如果需要在一个UIViewController中实现很复杂的View结构或者subViews之间的动画逻辑,那么如何合理设计UIViewControllerUIView两者之间的关系呢?

在上文中说过,我的想法是通过给每一个UIViewController设计一个对应的XXXContainerView,通过这样的方式来强行分离V和C,避免由于V太复杂时出现MassiveViewController.但这样同时也带来了一个坏处:无法像在UIViewController自带的view里添加控件一样,可以将控件的响应方法直接绑定到UIViewController的.m文件中,也无法享受类似viewDidDisappear:生命周期方法带来的便利了.

当然,对于有一定MVC经验的开发者,也可以通过类似下面的代码来简化XXXContainerView这一层:

[self.view addSubview:self.topView]; [self.view addSubview:self.midView]; [self.view addSubview:self.bottomView]; 

虽然任何Demo都不可能模拟出实际项目中遇到的问题,但通过不同横向对比还是很容易看出不同架构的区别所在.接下来,我将以我目前对MVC的理解,给出一个简单的登录示例Demo.

Demo地址:http://pan.baidu.com/s/1pLTCyEJ

Demo十分简单,这里仅做简单说明:

  1. LoginContainerView:负责创建用户所能看到的界面,以及将向Controller中传递登录事件和登录参数.
  2. LoginModel:提供接口完成具体的登录业务,Demo中省略了网络层以及存储层.
  3. 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的例子.通过二者横向对比,两者的差异会很明显的体现出来.

关于我们
首页
公司简介
课程专业
师资力量
高薪就业
青鸟课程
ACCP
学士后Java
基础教育
UI设计
回到首页