iOS 框架 Viper 初识
前言:
传统的MVC架构中,我们都知道,其Controller(控制器)层接纳了太多的任务,当开发不断进行,其内部的业务逻辑逐渐积累,最后则会变得臃肿不堪,不便于后期的调试测试以及多人协助,所以,我们需要寻找减轻Controller层负担的方法,而VIPER架构其实是将Controller再细分成三层,分别是View、Interactor、Presenter,已达到减轻Controller层负担的作用。
VIPER中每个字母的意思是如下:
V: View视图:在这里并不是指传统的UIView或其子类,事实上它就是UIViewController,在前面所说到,VIPER架构主要是将MVC架构中的Controller进行更加细致的划分,而View(视图)层则是主要负责一些视图的显示、布局,用户事件的接受以及转发,基本的显示逻辑处理等等工作。
I: Interactor交互器:其为VIPER的中心枢纽,主要负责交互的工作,例如数据的请求(网络请求、本地持久化层请求)、某些业务逻辑的处理,在这里我们得到的数据是原始数据,需要经过解析处理转换成能够直接应用于视图的视图模型数据,所以我们需要用到了下一层Presenter(展示器)。
P: Presenter展示器:当我们在上一层Interactor(交互器)中获得原始数据后,我们需要将数据进行解析处理,比如我们在交互器中进行了网络请求,得到了json数据,若要将json中所包含的内容显示出来,我们则需要将json数据进行解析,展示器就是专注于数据的解析转换,将原始的数据转换成最终能够直接显示在试图上的视图模型数据。此外,展示器中还带有路由器Router,可以进行路由的操作。
E: Entity实体模型对象
R: Router路由器: 负责视图的跳转,因为使用VIPER架构需要进行各层之间的相互绑定,所以视图的跳转不能简单地使用原始的方法
代码分析:
DEMO 下载地址: Viper_swift 这是一个 简单的 viper 的架构 展示了其中的数据流向 使用 swift 编写 如图 a 所示
简单的效果如下:
viper a1.0 Router
在demo 中 所有的页面的 来 控制页面的跳转
代码分析 在 Protocols.swift 中 枚举类型 root 代表设置 window 的 rootViewController
enum RouterType{
case root(identifier:String)
case push(identifier:String)
case modal(identifier:String)
case back
}
在 AppDelegate.swift 中 application 中我们调用了
Router(presenter: nil).route(type: .root(identifier: VIPERs.one.identifier), userInfo: nil) 来设置根视图。
如果要传参数 可以在 route 的方法中
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
window = UIWindow(frame: UIScreen.main.bounds)
window?.backgroundColor = UIColor.white
window?.makeKeyAndVisible()
// we need to set rootViewController for window
BinderHelper.initBinder()
// router to control ViewController jump
Router(presenter: nil).route(type: .root(identifier: VIPERs.one.identifier), userInfo: nil)
return true
}
2.0 Interactor
分别连接 了 presnter 和 View 数据从view 流向 interactor 里面做 网络数据请求 和 处理 。之后 流向 presentor 然后presentor 开始 流向 router 和 view 做处理。
如下所示
override func refresh(request: Request) {
let request = request as! OneRequest
switch request {
case .jump:
self.presenter.present(response: OneResponse.jumpResponse(viper: VIPERs.two))
// MARK: !!! 注意 这里 let 是很关键的 不然 会报错 无法找到 userName 和 password
case let .login(userName, password):
self.provider.request(.login(userName: userName, password: password), completion: { result in
var json: Any? = nil
switch result {
case .failure: ()
case let .success(response):
json = try? response.mapJSON()
print("login request success \(String(describing: json))")
}
self.presenter.present(response: OneResponse.loginResponse(json: json))
})
}
}
3 总结
不同于 MVC 框架 ,Viper 是每个ViewController 中都要 新建 View ,Presenter,Interactor 等。类的量要大些。